diff options
Diffstat (limited to 'linux/drivers/media/video/mxb.c')
-rw-r--r-- | linux/drivers/media/video/mxb.c | 108 |
1 files changed, 87 insertions, 21 deletions
diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index 5b3c4b824..ce8a4d9b4 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -33,6 +33,35 @@ #define I2C_SAA7111A 0x24 +/* All unused bytes are reserverd. */ +#define SAA711X_CHIP_VERSION 0x00 +#define SAA711X_ANALOG_INPUT_CONTROL_1 0x02 +#define SAA711X_ANALOG_INPUT_CONTROL_2 0x03 +#define SAA711X_ANALOG_INPUT_CONTROL_3 0x04 +#define SAA711X_ANALOG_INPUT_CONTROL_4 0x05 +#define SAA711X_HORIZONTAL_SYNC_START 0x06 +#define SAA711X_HORIZONTAL_SYNC_STOP 0x07 +#define SAA711X_SYNC_CONTROL 0x08 +#define SAA711X_LUMINANCE_CONTROL 0x09 +#define SAA711X_LUMINANCE_BRIGHTNESS 0x0A +#define SAA711X_LUMINANCE_CONTRAST 0x0B +#define SAA711X_CHROMA_SATURATION 0x0C +#define SAA711X_CHROMA_HUE_CONTROL 0x0D +#define SAA711X_CHROMA_CONTROL 0x0E +#define SAA711X_FORMAT_DELAY_CONTROL 0x10 +#define SAA711X_OUTPUT_CONTROL_1 0x11 +#define SAA711X_OUTPUT_CONTROL_2 0x12 +#define SAA711X_OUTPUT_CONTROL_3 0x13 +#define SAA711X_V_GATE_1_START 0x15 +#define SAA711X_V_GATE_1_STOP 0x16 +#define SAA711X_V_GATE_1_MSB 0x17 +#define SAA711X_TEXT_SLICER_STATUS 0x1A +#define SAA711X_DECODED_BYTES_OF_TS_1 0x1B +#define SAA711X_DECODED_BYTES_OF_TS_2 0x1C +#define SAA711X_STATUS_BYTE 0x1F + +#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) + /* global variable */ static int mxb_num = 0; @@ -129,6 +158,9 @@ static struct saa7146_extension_ioctls ioctls[] = { struct mxb { + struct video_device video_dev; + struct video_device vbi_dev; + struct i2c_adapter i2c_adapter; struct i2c_client* saa7111a; @@ -169,6 +201,10 @@ static int mxb_probe(struct saa7146_dev* dev, unsigned int subvendor, unsigned i } memset(mxb, 0x0, sizeof(struct mxb)); + /* FIXME: enable i2c-port pins, video-port-pins + video port pins should be enabled here ?! */ + saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); + saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); if(i2c_add_adapter(&mxb->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); @@ -396,7 +432,7 @@ err: return 0; } -/* interrupt bh-handler. this gets called when irq_mask is != 0. +/* interrupt-handler. this gets called when irq_mask is != 0. it must clear the interrupt-bits in irq_mask it has handled */ /* void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask) @@ -410,11 +446,26 @@ static int mxb_attach(struct saa7146_dev* dev) { struct mxb* mxb = (struct mxb*)dev->ext_priv; + DEB_EE(("dev:%p\n",dev)); + /* checking for i2c-devices can be omitted here, because we already did this in "mxb_vl42_probe" */ - mxb_num++; + saa7146_video_uops.init(dev); + if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { + ERR(("cannot register capture v4l2 device. skipping.\n")); + return -1; + } + /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ + if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { + saa7146_vbi_uops.init(dev); + if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { + ERR(("cannot register vbi v4l2 device. skipping.\n")); + return -1; + } + } + i2c_inc_use_client(mxb->tea6420_1); i2c_inc_use_client(mxb->tea6420_2); i2c_inc_use_client(mxb->tea6415c); @@ -422,6 +473,7 @@ static int mxb_attach(struct saa7146_dev* dev) i2c_inc_use_client(mxb->saa7111a); i2c_inc_use_client(mxb->tuner); + mxb_num++; return mxb_init_done(dev); } @@ -429,6 +481,8 @@ static int mxb_detach(struct saa7146_dev* dev) { struct mxb* mxb = (struct mxb*)dev->ext_priv; + DEB_EE(("dev:%p\n",dev)); + i2c_dec_use_client(mxb->tea6420_1); i2c_dec_use_client(mxb->tea6420_2); i2c_dec_use_client(mxb->tea6415c); @@ -436,6 +490,11 @@ static int mxb_detach(struct saa7146_dev* dev) i2c_dec_use_client(mxb->saa7111a); i2c_dec_use_client(mxb->tuner); + saa7146_unregister_device(&mxb->video_dev,dev); + if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { + saa7146_unregister_device(&mxb->vbi_dev,dev); + } + mxb_num--; i2c_del_adapter(&mxb->i2c_adapter); @@ -447,16 +506,25 @@ static int mxb_detach(struct saa7146_dev* dev) static int mxb_vbi_bypass(struct saa7146_dev* dev) { struct mxb* mxb = (struct mxb*)dev->ext_priv; - int i = 1; + s32 byte = 0x0; + int result = 0; - /* switch bypass in saa7111a */ - /* fixme saa - if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,SAA711X_VBI_BYPASS, &i)) { - DEB_D(("could not address saa7111a.\n")); - return -1; - } - */ - + DEB_EE(("dev:%p\n",dev)); + + /* switch bypass in saa7111a, this should be done in the + saa7111a driver of course... */ + if ( -1 == (result = i2c_smbus_read_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_3))) { + DEB_D(("could not read from saa7111a.\n")); + return -EFAULT; + } + byte = result; + byte &= 0xf0; + byte |= 0x0a; + + if ( 0 != (result = i2c_smbus_write_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_3, byte))) { + DEB_D(("could not write to saa7111a.\n")); + return -EFAULT; + } return 0; } @@ -464,12 +532,13 @@ static int mxb_vbi_bypass(struct saa7146_dev* dev) static int saa7111_set_gpio(struct saa7146_dev *dev, int bl) { struct mxb* mxb = (struct mxb*)dev->ext_priv; - s32 byte = 0x0; int result = 0; + DEB_EE(("dev:%p\n",dev)); + /* get the old register contents */ - if ( -1 == (byte = i2c_smbus_read_byte_data(mxb->saa7111a, 0x11))) { + if ( -1 == (byte = i2c_smbus_read_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_1))) { DEB_D(("could not read from saa711x\n")); return -EFAULT; } @@ -481,7 +550,7 @@ static int saa7111_set_gpio(struct saa7146_dev *dev, int bl) } /* write register contents back */ - if ( 0 != (result = i2c_smbus_write_byte_data(mxb->saa7111a, 0x11, byte))) { + if ( 0 != (result = i2c_smbus_write_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_1, byte))) { DEB_D(("could not write to saa711x\n")); return -EFAULT; } @@ -707,11 +776,10 @@ static int mxb_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) strcpy(t->name, "Television"); t->type = V4L2_TUNER_ANALOG_TV; - /* fixme: _CAP_NORM needed? */ t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */ t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */ - /* fixme: add the real signal strength here */ + /* FIXME: add the real signal strength here */ t->signal = 0xffff; t->afc = 0; @@ -953,10 +1021,10 @@ struct saa7146_extension extension = { .name = MXB_IDENTIFIER, .inputs = MXB_INPUTS, .audios = MXB_AUDIOS, - .capabilities = V4L2_CAP_TUNER, + .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE, + + .flags = 0, - .flags = SAA7146_EXT_PROVIDES_VIDEO|SAA7146_EXT_PROVIDES_VBI, - .devices = &sub_data[0], .module = THIS_MODULE, @@ -969,8 +1037,6 @@ struct saa7146_extension extension = { .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), .std_callback = &std_callback, - .vbi = mxb_vbi_bypass, - .ioctls = &ioctls[0], .preinit = mxb_preinit, |