diff options
author | Antti Palosaari <crope@iki.fi> | 2013-03-08 14:54:09 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-21 18:06:00 -0400 |
commit | 3bf5e55299ac5a389a4e6b9991f900579a765172 (patch) | |
tree | 382b4a698493a3d57896c553b3e27f21ff5e5ff1 | |
parent | 0c13c54d8527df03decf7c522f35886fb721f282 (diff) |
[media] af9033: implement i/o optimized reg table writer
Use register address auto increment to reduce I/O when large
register / values tables are written.
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/dvb-frontends/af9033.c | 47 |
1 files changed, 37 insertions, 10 deletions
diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index 2dba516d5680..a777b4b944eb 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c | |||
@@ -156,6 +156,37 @@ static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val, | |||
156 | return 0; | 156 | return 0; |
157 | } | 157 | } |
158 | 158 | ||
159 | /* write reg val table using reg addr auto increment */ | ||
160 | static int af9033_wr_reg_val_tab(struct af9033_state *state, | ||
161 | const struct reg_val *tab, int tab_len) | ||
162 | { | ||
163 | int ret, i, j; | ||
164 | u8 buf[tab_len]; | ||
165 | |||
166 | dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len); | ||
167 | |||
168 | for (i = 0, j = 0; i < tab_len; i++) { | ||
169 | buf[j] = tab[i].val; | ||
170 | |||
171 | if (i == tab_len - 1 || tab[i].reg != tab[i + 1].reg - 1) { | ||
172 | ret = af9033_wr_regs(state, tab[i].reg - j, buf, j + 1); | ||
173 | if (ret < 0) | ||
174 | goto err; | ||
175 | |||
176 | j = 0; | ||
177 | } else { | ||
178 | j++; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | return 0; | ||
183 | |||
184 | err: | ||
185 | dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
186 | |||
187 | return ret; | ||
188 | } | ||
189 | |||
159 | static u32 af9033_div(struct af9033_state *state, u32 a, u32 b, u32 x) | 190 | static u32 af9033_div(struct af9033_state *state, u32 a, u32 b, u32 x) |
160 | { | 191 | { |
161 | u32 r = 0, c = 0, i; | 192 | u32 r = 0, c = 0, i; |
@@ -306,11 +337,9 @@ static int af9033_init(struct dvb_frontend *fe) | |||
306 | break; | 337 | break; |
307 | } | 338 | } |
308 | 339 | ||
309 | for (i = 0; i < len; i++) { | 340 | ret = af9033_wr_reg_val_tab(state, init, len); |
310 | ret = af9033_wr_reg(state, init[i].reg, init[i].val); | 341 | if (ret < 0) |
311 | if (ret < 0) | 342 | goto err; |
312 | goto err; | ||
313 | } | ||
314 | 343 | ||
315 | /* load tuner specific settings */ | 344 | /* load tuner specific settings */ |
316 | dev_dbg(&state->i2c->dev, "%s: load tuner specific settings\n", | 345 | dev_dbg(&state->i2c->dev, "%s: load tuner specific settings\n", |
@@ -371,11 +400,9 @@ static int af9033_init(struct dvb_frontend *fe) | |||
371 | goto err; | 400 | goto err; |
372 | } | 401 | } |
373 | 402 | ||
374 | for (i = 0; i < len; i++) { | 403 | ret = af9033_wr_reg_val_tab(state, init, len); |
375 | ret = af9033_wr_reg(state, init[i].reg, init[i].val); | 404 | if (ret < 0) |
376 | if (ret < 0) | 405 | goto err; |
377 | goto err; | ||
378 | } | ||
379 | 406 | ||
380 | if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { | 407 | if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { |
381 | ret = af9033_wr_reg_mask(state, 0x00d91c, 0x01, 0x01); | 408 | ret = af9033_wr_reg_mask(state, 0x00d91c, 0x01, 0x01); |