Commit 16af6f5a authored by Devin Heitmueller's avatar Devin Heitmueller Committed by Mauro Carvalho Chehab

V4L/DVB (11343): au0828: make i2c clock speed per-board configurable

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: default avatarDevin Heitmueller <dheitmueller@linuxtv.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 9beb0de9
...@@ -46,6 +46,7 @@ struct au0828_board au0828_boards[] = { ...@@ -46,6 +46,7 @@ struct au0828_board au0828_boards[] = {
.name = "Hauppauge HVR850", .name = "Hauppauge HVR850",
.tuner_type = TUNER_XC5000, .tuner_type = TUNER_XC5000,
.tuner_addr = 0x61, .tuner_addr = 0x61,
.i2c_clk_divider = AU0828_I2C_CLK_30KHZ,
.input = { .input = {
{ {
.type = AU0828_VMUX_TELEVISION, .type = AU0828_VMUX_TELEVISION,
...@@ -70,6 +71,13 @@ struct au0828_board au0828_boards[] = { ...@@ -70,6 +71,13 @@ struct au0828_board au0828_boards[] = {
.name = "Hauppauge HVR950Q", .name = "Hauppauge HVR950Q",
.tuner_type = TUNER_XC5000, .tuner_type = TUNER_XC5000,
.tuner_addr = 0x61, .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 = { .input = {
{ {
.type = AU0828_VMUX_TELEVISION, .type = AU0828_VMUX_TELEVISION,
...@@ -94,16 +102,19 @@ struct au0828_board au0828_boards[] = { ...@@ -94,16 +102,19 @@ struct au0828_board au0828_boards[] = {
.name = "Hauppauge HVR950Q rev xxF8", .name = "Hauppauge HVR950Q rev xxF8",
.tuner_type = UNSET, .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET, .tuner_addr = ADDR_UNSET,
.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
}, },
[AU0828_BOARD_DVICO_FUSIONHDTV7] = { [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
.name = "DViCO FusionHDTV USB", .name = "DViCO FusionHDTV USB",
.tuner_type = UNSET, .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET, .tuner_addr = ADDR_UNSET,
.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
}, },
[AU0828_BOARD_HAUPPAUGE_WOODBURY] = { [AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
.name = "Hauppauge Woodbury", .name = "Hauppauge Woodbury",
.tuner_type = UNSET, .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET, .tuner_addr = ADDR_UNSET,
.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
}, },
}; };
......
...@@ -146,16 +146,9 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, ...@@ -146,16 +146,9 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
/* FIXME: There is a problem with i2c communications with xc5000 that /* Set the I2C clock */
requires us to slow down the i2c clock until we have a better au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
strategy (such as using the secondary i2c bus to do firmware dev->board.i2c_clk_divider);
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);
/* Hardware needs 8 bit addresses */ /* Hardware needs 8 bit addresses */
au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
...@@ -230,16 +223,9 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, ...@@ -230,16 +223,9 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
/* FIXME: There is a problem with i2c communications with xc5000 that /* Set the I2C clock */
requires us to slow down the i2c clock until we have a better au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
strategy (such as using the secondary i2c bus to do firmware dev->board.i2c_clk_divider);
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);
/* Hardware needs 8 bit addresses */ /* Hardware needs 8 bit addresses */
au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
......
...@@ -81,6 +81,7 @@ struct au0828_board { ...@@ -81,6 +81,7 @@ struct au0828_board {
char *name; char *name;
unsigned int tuner_type; unsigned int tuner_type;
unsigned char tuner_addr; unsigned char tuner_addr;
unsigned char i2c_clk_divider;
struct au0828_input input[AU0828_MAX_INPUT]; struct au0828_input input[AU0828_MAX_INPUT];
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment