V4L/DVB (11343): au0828: make i2c clock speed per-board configurable
Devin Heitmueller [Wed, 1 Apr 2009 03:11:31 +0000 (00:11 -0300)]
Setup the i2c clock speed to be definable on a per-board basis.  This allows
us to explicitly set the clock speed to 30 KHz on the 950q, and also gets rid
of code which sets it on a basis of what chip the i2c master is talking to
at any given time (which could have caused issues because i2c slaves should
never receive commands at a clock higher than their supported clock speed).

Signed-off-by: Devin Heitmueller <dheitmueller@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

drivers/media/video/au0828/au0828-cards.c
drivers/media/video/au0828/au0828-i2c.c
drivers/media/video/au0828/au0828.h

index 1aabaa7..abba48b 100644 (file)
@@ -46,6 +46,7 @@ struct au0828_board au0828_boards[] = {
                .name   = "Hauppauge HVR850",
                .tuner_type = TUNER_XC5000,
                .tuner_addr = 0x61,
+               .i2c_clk_divider = AU0828_I2C_CLK_30KHZ,
                .input = {
                        {
                                .type = AU0828_VMUX_TELEVISION,
@@ -70,6 +71,13 @@ struct au0828_board au0828_boards[] = {
                .name   = "Hauppauge HVR950Q",
                .tuner_type = TUNER_XC5000,
                .tuner_addr = 0x61,
+               /* The au0828 hardware i2c implementation does not properly
+                  support the xc5000's i2c clock stretching.  So we need to
+                  lower the clock frequency enough where the 15us clock
+                  stretch fits inside of a normal clock cycle, or else the
+                  au0828 fails to set the STOP bit.  A 30 KHz clock puts the
+                  clock pulse width at 18us */
+               .i2c_clk_divider = AU0828_I2C_CLK_30KHZ,
                .input = {
                        {
                                .type = AU0828_VMUX_TELEVISION,
@@ -94,16 +102,19 @@ struct au0828_board au0828_boards[] = {
                .name   = "Hauppauge HVR950Q rev xxF8",
                .tuner_type = UNSET,
                .tuner_addr = ADDR_UNSET,
+               .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
        },
        [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
                .name   = "DViCO FusionHDTV USB",
                .tuner_type = UNSET,
                .tuner_addr = ADDR_UNSET,
+               .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
        },
        [AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
                .name = "Hauppauge Woodbury",
                .tuner_type = UNSET,
                .tuner_addr = ADDR_UNSET,
+               .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
        },
 };
 
index 27dcfc6..13e4943 100644 (file)
@@ -146,16 +146,9 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
 
        au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
 
-       /* FIXME: There is a problem with i2c communications with xc5000 that
-          requires us to slow down the i2c clock until we have a better
-          strategy (such as using the secondary i2c bus to do firmware
-          loading */
-       if ((msg->addr << 1) == 0xc2)
-               au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
-                            AU0828_I2C_CLK_30KHZ);
-       else
-               au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
-                            AU0828_I2C_CLK_250KHZ);
+       /* Set the I2C clock */
+       au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
+                    dev->board.i2c_clk_divider);
 
        /* Hardware needs 8 bit addresses */
        au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
@@ -230,16 +223,9 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
 
        au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
 
-       /* FIXME: There is a problem with i2c communications with xc5000 that
-          requires us to slow down the i2c clock until we have a better
-          strategy (such as using the secondary i2c bus to do firmware
-          loading */
-       if ((msg->addr << 1) == 0xc2)
-               au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
-                            AU0828_I2C_CLK_30KHZ);
-       else
-               au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
-                            AU0828_I2C_CLK_250KHZ);
+       /* Set the I2C clock */
+       au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
+                    dev->board.i2c_clk_divider);
 
        /* Hardware needs 8 bit addresses */
        au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
index 6ed1a61..b977915 100644 (file)
@@ -81,6 +81,7 @@ struct au0828_board {
        char *name;
        unsigned int tuner_type;
        unsigned char tuner_addr;
+       unsigned char i2c_clk_divider;
        struct au0828_input input[AU0828_MAX_INPUT];
 
 };