aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <m.chehab@samsung.com>2014-07-25 13:02:14 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-07-30 14:44:25 -0400
commitcfd0c77d0830d33288e9da17aa10db3a61de601a (patch)
tree5c5bdd468bc6a3b7c7f4ddba3fed70c4e8d9743e /drivers/media
parent7f196789b3ffee243b681d3e7dab8890038db856 (diff)
[media] au0828: improve I2C speed
Commits 21dc61d3c0a4 and 7a1dd50b89d4 reduced the board I2C speed to 20 MHz by default, due to a I2C stretch issue: while xc5000 uses i2c stretch when a command is sent to it, au0828 doesn't support this feature. However, this is needed only for Xceive tuners. The other I2C devices can work at the max speed. So, revert the workarounds at board level, handling it at I2C level, only when talking with xc5000. Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/usb/au0828/au0828-cards.c6
-rw-r--r--drivers/media/usb/au0828/au0828-i2c.c37
2 files changed, 27 insertions, 16 deletions
diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c
index 7fdadf9bc90b..3a7924044a87 100644
--- a/drivers/media/usb/au0828/au0828-cards.c
+++ b/drivers/media/usb/au0828/au0828-cards.c
@@ -46,7 +46,7 @@ struct au0828_board au0828_boards[] = {
46 .name = "Hauppauge HVR850", 46 .name = "Hauppauge HVR850",
47 .tuner_type = TUNER_XC5000, 47 .tuner_type = TUNER_XC5000,
48 .tuner_addr = 0x61, 48 .tuner_addr = 0x61,
49 .i2c_clk_divider = AU0828_I2C_CLK_20KHZ, 49 .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
50 .input = { 50 .input = {
51 { 51 {
52 .type = AU0828_VMUX_TELEVISION, 52 .type = AU0828_VMUX_TELEVISION,
@@ -77,7 +77,7 @@ struct au0828_board au0828_boards[] = {
77 stretch fits inside of a normal clock cycle, or else the 77 stretch fits inside of a normal clock cycle, or else the
78 au0828 fails to set the STOP bit. A 30 KHz clock puts the 78 au0828 fails to set the STOP bit. A 30 KHz clock puts the
79 clock pulse width at 18us */ 79 clock pulse width at 18us */
80 .i2c_clk_divider = AU0828_I2C_CLK_20KHZ, 80 .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
81 .input = { 81 .input = {
82 { 82 {
83 .type = AU0828_VMUX_TELEVISION, 83 .type = AU0828_VMUX_TELEVISION,
@@ -108,7 +108,7 @@ struct au0828_board au0828_boards[] = {
108 .name = "DViCO FusionHDTV USB", 108 .name = "DViCO FusionHDTV USB",
109 .tuner_type = UNSET, 109 .tuner_type = UNSET,
110 .tuner_addr = ADDR_UNSET, 110 .tuner_addr = ADDR_UNSET,
111 .i2c_clk_divider = AU0828_I2C_CLK_20KHZ, 111 .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
112 }, 112 },
113 [AU0828_BOARD_HAUPPAUGE_WOODBURY] = { 113 [AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
114 .name = "Hauppauge Woodbury", 114 .name = "Hauppauge Woodbury",
diff --git a/drivers/media/usb/au0828/au0828-i2c.c b/drivers/media/usb/au0828/au0828-i2c.c
index 17ec3651b10e..daaeaf1b089c 100644
--- a/drivers/media/usb/au0828/au0828-i2c.c
+++ b/drivers/media/usb/au0828/au0828-i2c.c
@@ -141,25 +141,27 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
141{ 141{
142 int i, strobe = 0; 142 int i, strobe = 0;
143 struct au0828_dev *dev = i2c_adap->algo_data; 143 struct au0828_dev *dev = i2c_adap->algo_data;
144 u8 i2c_speed = dev->board.i2c_clk_divider;
144 145
145 dprintk(4, "%s()\n", __func__); 146 dprintk(4, "%s()\n", __func__);
146 147
147 au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); 148 au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
148 149
149 /* Set the I2C clock */
150 if (((dev->board.tuner_type == TUNER_XC5000) || 150 if (((dev->board.tuner_type == TUNER_XC5000) ||
151 (dev->board.tuner_type == TUNER_XC5000C)) && 151 (dev->board.tuner_type == TUNER_XC5000C)) &&
152 (dev->board.tuner_addr == msg->addr) && 152 (dev->board.tuner_addr == msg->addr)) {
153 (msg->len == 64)) { 153 /*
154 /* Hack to speed up firmware load. The xc5000 lets us do up 154 * Due to I2C clock stretch, we need to use a lower speed
155 to 400 KHz when in firmware download mode */ 155 * on xc5000 for commands. However, firmware transfer can
156 au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, 156 * speed up to 400 KHz.
157 AU0828_I2C_CLK_250KHZ); 157 */
158 } else { 158 if (msg->len == 64)
159 /* Use the i2c clock speed in the board configuration */ 159 i2c_speed = AU0828_I2C_CLK_250KHZ;
160 au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, 160 else
161 dev->board.i2c_clk_divider); 161 i2c_speed = AU0828_I2C_CLK_20KHZ;
162 } 162 }
163 /* Set the I2C clock */
164 au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed);
163 165
164 /* Hardware needs 8 bit addresses */ 166 /* Hardware needs 8 bit addresses */
165 au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); 167 au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
@@ -228,15 +230,24 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
228 const struct i2c_msg *msg, int joined) 230 const struct i2c_msg *msg, int joined)
229{ 231{
230 struct au0828_dev *dev = i2c_adap->algo_data; 232 struct au0828_dev *dev = i2c_adap->algo_data;
233 u8 i2c_speed = dev->board.i2c_clk_divider;
231 int i; 234 int i;
232 235
233 dprintk(4, "%s()\n", __func__); 236 dprintk(4, "%s()\n", __func__);
234 237
235 au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); 238 au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
236 239
240 /*
241 * Due to xc5000c clock stretch, we cannot use full speed at
242 * readings from xc5000, as otherwise they'll fail.
243 */
244 if (((dev->board.tuner_type == TUNER_XC5000) ||
245 (dev->board.tuner_type == TUNER_XC5000C)) &&
246 (dev->board.tuner_addr == msg->addr))
247 i2c_speed = AU0828_I2C_CLK_20KHZ;
248
237 /* Set the I2C clock */ 249 /* Set the I2C clock */
238 au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, 250 au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed);
239 dev->board.i2c_clk_divider);
240 251
241 /* Hardware needs 8 bit addresses */ 252 /* Hardware needs 8 bit addresses */
242 au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); 253 au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);