On Sun, 2009-07-19 at 15:38 +0200, Jean Delvare wrote:
> Hi Andy,
Jean,
Thanks for tking the time to answer my questions and review. My
responses are inline.
> On Fri, 17 Jul 2009 16:46:55 -0400, Andy Walls wrote:
> > This patch add support to the cx18 driver for setting up the
> > Z8F0811/Hauppauge IR Tx/Rx chip with the i2c binding model in newer
> > kernels.
> >
> > My concerns/questions:
> >
> > 1. When using the new i2c binding model, I'm not saving the returned
> > pointer from i2c_new_probed_device() and am hence taking no action on
> > trying to clean up IR i2c devices on module unload. Will the i2c
> > subsystem clean up this automatically when the adapter is unregistered
> > on module unload?
>
> While this isn't currently documented, yes it will. If this ever
> changes, I will first let i2c-core emit warnings and still clean up
> orphan clients. But I suspect the current behavior is easier for
> everyone and I couldn't see any reason to change it at this point.
OK. Sounds good. :)
> > 2. When using the new i2c binding model, I'm calling
> > i2c_new_probed_device() twice: once for Rx (addr 0x71 of the Z8F0811)
> > and another time for Tx (addr 0x70 of the Z8F0811). Is it a problem to
> > have two Linux i2c devices for two distinct addresses of the same
> > underlying hardware device?
>
> No, this is not a problem. The fact that this is the same device behind
> both addresses is an implementation detail. As long as both functions
> are independent, it should work just fine.
OK. :)
> > 3. When using the new i2c binding model, I opted not to use ir_video for
> > the Z8F0811 loaded with microcode from Zilog/Hauppauge. Since I needed
> > one name for Rx binding and one for Tx binding, I used these names:
> >
> > "ir_tx_z8f0811_haup"
> > "ir_rx_z8f0811_haup"
> >
> > [Which is ir_(func)_(part number)_(firmware_oem)]. It made sense to me.
> > I assume these are the names to which ir-kbd-i2c and lirc_* will have to
> > bind. Is that correct?
>
> Yes, this is correct, and the approach is good.
OK. :)
> Ideally the "ir_video"
> type would not exist (or would go away over time) and we would have a
> separate type name for each IR chip, resulting in much cleaner code.
> The reason for the current implementation is solely historical.
OK, I had suspected the reason was this.
> Review:
>
> > diff -r d754a2d5a376 linux/drivers/media/video/cx18/cx18-cards.c
> > --- a/linux/drivers/media/video/cx18/cx18-cards.c Wed Jul 15 07:28:02
> > 2009 -0300
> > +++ b/linux/drivers/media/video/cx18/cx18-cards.c Fri Jul 17 16:05:28
> > 2009 -0400
> > @@ -56,7 +56,8 @@
> > .hw_audio_ctrl = CX18_HW_418_AV,
> > .hw_muxer = CX18_HW_CS5345,
> > .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
> > - CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
> > + CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
> > + CX18_HW_Z8F0811_IR_HAUP,
> > .video_inputs = {
> > { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 },
> > { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 },
> > @@ -102,7 +103,8 @@
> > .hw_audio_ctrl = CX18_HW_418_AV,
> > .hw_muxer = CX18_HW_CS5345,
> > .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
> > - CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
> > + CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
> > + CX18_HW_Z8F0811_IR_HAUP,
> > .video_inputs = {
> > { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 },
> > { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 },
> > diff -r d754a2d5a376 linux/drivers/media/video/cx18/cx18-cards.h
> > --- a/linux/drivers/media/video/cx18/cx18-cards.h Wed Jul 15 07:28:02
> > 2009 -0300
> > +++ b/linux/drivers/media/video/cx18/cx18-cards.h Fri Jul 17 16:05:28
> > 2009 -0400
> > @@ -22,13 +22,17 @@
> > */
> >
> > /* hardware flags */
> > -#define CX18_HW_TUNER (1 << 0)
> > -#define CX18_HW_TVEEPROM (1 << 1)
> > -#define CX18_HW_CS5345 (1 << 2)
> > -#define CX18_HW_DVB (1 << 3)
> > -#define CX18_HW_418_AV (1 << 4)
> > -#define CX18_HW_GPIO_MUX (1 << 5)
> > -#define CX18_HW_GPIO_RESET_CTRL (1 << 6)
> > +#define CX18_HW_TUNER (1 << 0)
> > +#define CX18_HW_TVEEPROM (1 << 1)
> > +#define CX18_HW_CS5345 (1 << 2)
> > +#define CX18_HW_DVB (1 << 3)
> > +#define CX18_HW_418_AV (1 << 4)
> > +#define CX18_HW_GPIO_MUX (1 << 5)
> > +#define CX18_HW_GPIO_RESET_CTRL (1 << 6)
> > +#define CX18_HW_Z8F0811_IR_TX_HAUP (1 << 7)
> > +#define CX18_HW_Z8F0811_IR_RX_HAUP (1 << 8)
> > +#define CX18_HW_Z8F0811_IR_HAUP (CX18_HW_Z8F0811_IR_RX_HAUP | \
> > + CX18_HW_Z8F0811_IR_TX_HAUP)
> >
> > /* video inputs */
> > #define CX18_CARD_INPUT_VID_TUNER 1
> > diff -r d754a2d5a376 linux/drivers/media/video/cx18/cx18-i2c.c
> > --- a/linux/drivers/media/video/cx18/cx18-i2c.c Wed Jul 15 07:28:02
> > 2009 -0300
> > +++ b/linux/drivers/media/video/cx18/cx18-i2c.c Fri Jul 17 16:05:28
> > 2009 -0400
> > @@ -40,16 +40,20 @@
> > #define GETSDL_BIT 0x0008
> >
> > #define CX18_CS5345_I2C_ADDR 0x4c
> > +#define CX18_Z8F0811_IR_TX_I2C_ADDR 0x70
> > +#define CX18_Z8F0811_IR_RX_I2C_ADDR 0x71
> >
> > /* This array should match the CX18_HW_ defines */
> > static const u8 hw_addrs[] = {
> > - 0, /* CX18_HW_TUNER */
> > - 0, /* CX18_HW_TVEEPROM */
> > - CX18_CS5345_I2C_ADDR, /* CX18_HW_CS5345 */
> > - 0, /* CX18_HW_DVB */
> > - 0, /* CX18_HW_418_AV */
> > - 0, /* CX18_HW_GPIO_MUX */
> > - 0, /* CX18_HW_GPIO_RESET_CTRL */
> > + 0, /* CX18_HW_TUNER */
> > + 0, /* CX18_HW_TVEEPROM */
> > + CX18_CS5345_I2C_ADDR, /* CX18_HW_CS5345 */
> > + 0, /* CX18_HW_DVB */
> > + 0, /* CX18_HW_418_AV */
> > + 0, /* CX18_HW_GPIO_MUX */
> > + 0, /* CX18_HW_GPIO_RESET_CTRL */
> > + CX18_Z8F0811_IR_TX_I2C_ADDR, /* CX18_HW_Z8F0811_IR_TX_HAUP */
> > + CX18_Z8F0811_IR_RX_I2C_ADDR, /* CX18_HW_Z8F0811_IR_RX_HAUP */
> > };
> >
> > /* This array should match the CX18_HW_ defines */
> > @@ -62,6 +66,8 @@
> > 0, /* CX18_HW_418_AV */
> > 0, /* CX18_HW_GPIO_MUX */
> > 0, /* CX18_HW_GPIO_RESET_CTRL */
> > + 0, /* CX18_HW_Z8F0811_IR_TX_HAUP */
> > + 0, /* CX18_HW_Z8F0811_IR_RX_HAUP */
> > };
> >
> > /* This array should match the CX18_HW_ defines */
> > @@ -73,6 +79,8 @@
> > NULL, /* CX18_HW_418_AV */
> > NULL, /* CX18_HW_GPIO_MUX */
> > NULL, /* CX18_HW_GPIO_RESET_CTRL */
> > + NULL, /* CX18_HW_Z8F0811_IR_TX_HAUP */
> > + NULL, /* CX18_HW_Z8F0811_IR_RX_HAUP */
> > };
> >
> > /* This array should match the CX18_HW_ defines */
> > @@ -84,8 +92,43 @@
> > "cx23418_AV",
> > "gpio_mux",
> > "gpio_reset_ctrl",
> > + "ir_tx_z8f0811_haup",
> > + "ir_rx_z8f0811_haup",
> > };
> >
> > +static int cx18_i2c_new_ir(struct i2c_adapter *adap, u32 hw, const char
> > *type,
> > + u8 addr)
> > +{
> > +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
> > + struct i2c_board_info info;
> > + struct IR_i2c_init_data ir_init_data;
> > + unsigned short addr_list[2] = { addr, I2C_CLIENT_END };
> > +
> > + memset(&info, 0, sizeof(struct i2c_board_info));
> > + strlcpy(info.type, type, I2C_NAME_SIZE);
> > +
> > + /* Our default information for ir-kbd-i2c.c to use */
> > + memset(&ir_init_data, 0, sizeof(struct IR_i2c_init_data));
> > + switch (hw) {
> > + case CX18_HW_Z8F0811_IR_RX_HAUP:
> > + ir_init_data.ir_codes = ir_codes_hauppauge_new;
> > + ir_init_data.get_key = NULL;
>
> This is a no-op, as ir_init_data was cleared with memset() right above.
Agree. I'll get rid of it.
>
> > + ir_init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
> > + ir_init_data.type = IR_TYPE_RC5;
> > + ir_init_data.name = "CX23418 Z8F0811 Hauppauge";
> > + break;
> > + default:
> > + break;
> > + }
> > + if (ir_init_data.name)
> > + info.platform_data = &ir_init_data;
>
> Not sure why you don't just put this in the switch to save a test? Even
> the memset could go there as far as I can see.
If this were the only I2C IR Rx device I had plans for in the cx18
driver, I would have used an if() statement for the whole thing instead
of a switch(). However, the LeadTek boards have an IR device that I
plan to support someday, so I left the common elements split out.
The biggest penalty here is probably the memset() for the IR Tx portion
of the Z8F0811 chip that doesn't use the ir_init_data, so I'll make the
change as you suggest.
> > +
> > + return i2c_new_probed_device(adap, &info, addr_list) == NULL ? -1 : 0;
> > +#else
> > + return -1;
> > +#endif
> > +}
> > +
> > int cx18_i2c_register(struct cx18 *cx, unsigned idx)
> > {
> > struct v4l2_subdev *sd;
> > @@ -119,7 +162,10 @@
> > if (!hw_addrs[idx])
> > return -1;
> >
> > - /* It's an I2C device other than an analog tuner */
> > + if (hw & CX18_HW_Z8F0811_IR_HAUP)
> > + return cx18_i2c_new_ir(adap, hw, type, hw_addrs[idx]);
>
> For consistency I'd move this up a bit (although I agree it is
> functionally equivalent.)
No problem.
> > +
> > + /* It's an I2C device other than an analog tuner or IR chip */
> > sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, mod, type, hw_addrs[idx]);
> > if (sd != NULL)
> > sd->grp_id = hw;
> >
> >
>
> The rest looks OK.
OK. Thanks.
-Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html