diff options
-rw-r--r-- | drivers/media/video/cx25840/cx25840-audio.c | 44 | ||||
-rw-r--r-- | drivers/media/video/cx25840/cx25840-core.c | 113 | ||||
-rw-r--r-- | drivers/media/video/cx25840/cx25840-core.h | 1 | ||||
-rw-r--r-- | drivers/media/video/cx25840/cx25840-firmware.c | 11 |
4 files changed, 148 insertions, 21 deletions
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index 93d74bee292a..d2faeaa79759 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c | |||
@@ -32,7 +32,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
32 | 32 | ||
33 | /* common for all inputs and rates */ | 33 | /* common for all inputs and rates */ |
34 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ | 34 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ |
35 | if (!state->is_cx23885) | 35 | if (!state->is_cx23885 && !state->is_cx231xx) |
36 | cx25840_write(client, 0x127, 0x50); | 36 | cx25840_write(client, 0x127, 0x50); |
37 | 37 | ||
38 | if (state->aud_input != CX25840_AUDIO_SERIAL) { | 38 | if (state->aud_input != CX25840_AUDIO_SERIAL) { |
@@ -43,11 +43,15 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
43 | * so avoid destroying registers. */ | 43 | * so avoid destroying registers. */ |
44 | break; | 44 | break; |
45 | } | 45 | } |
46 | /* VID_PLL and AUX_PLL */ | ||
47 | cx25840_write4(client, 0x108, 0x1006040f); | ||
48 | 46 | ||
49 | /* AUX_PLL_FRAC */ | 47 | if (!state->is_cx231xx) { |
50 | cx25840_write4(client, 0x110, 0x01bb39ee); | 48 | |
49 | /* VID_PLL and AUX_PLL */ | ||
50 | cx25840_write4(client, 0x108, 0x1006040f); | ||
51 | |||
52 | /* AUX_PLL_FRAC */ | ||
53 | cx25840_write4(client, 0x110, 0x01bb39ee); | ||
54 | } | ||
51 | 55 | ||
52 | if (state->is_cx25836) | 56 | if (state->is_cx25836) |
53 | break; | 57 | break; |
@@ -64,11 +68,15 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
64 | * so avoid destroying registers. */ | 68 | * so avoid destroying registers. */ |
65 | break; | 69 | break; |
66 | } | 70 | } |
67 | /* VID_PLL and AUX_PLL */ | ||
68 | cx25840_write4(client, 0x108, 0x1009040f); | ||
69 | 71 | ||
70 | /* AUX_PLL_FRAC */ | 72 | if (!state->is_cx231xx) { |
71 | cx25840_write4(client, 0x110, 0x00ec6bd6); | 73 | |
74 | /* VID_PLL and AUX_PLL */ | ||
75 | cx25840_write4(client, 0x108, 0x1009040f); | ||
76 | |||
77 | /* AUX_PLL_FRAC */ | ||
78 | cx25840_write4(client, 0x110, 0x00ec6bd6); | ||
79 | } | ||
72 | 80 | ||
73 | if (state->is_cx25836) | 81 | if (state->is_cx25836) |
74 | break; | 82 | break; |
@@ -85,11 +93,15 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
85 | * so avoid destroying registers. */ | 93 | * so avoid destroying registers. */ |
86 | break; | 94 | break; |
87 | } | 95 | } |
96 | |||
97 | if (!state->is_cx231xx) { | ||
98 | |||
88 | /* VID_PLL and AUX_PLL */ | 99 | /* VID_PLL and AUX_PLL */ |
89 | cx25840_write4(client, 0x108, 0x100a040f); | 100 | cx25840_write4(client, 0x108, 0x100a040f); |
90 | 101 | ||
91 | /* AUX_PLL_FRAC */ | 102 | /* AUX_PLL_FRAC */ |
92 | cx25840_write4(client, 0x110, 0x0098d6e5); | 103 | cx25840_write4(client, 0x110, 0x0098d6e5); |
104 | } | ||
93 | 105 | ||
94 | if (state->is_cx25836) | 106 | if (state->is_cx25836) |
95 | break; | 107 | break; |
@@ -108,11 +120,15 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
108 | * so avoid destroying registers. */ | 120 | * so avoid destroying registers. */ |
109 | break; | 121 | break; |
110 | } | 122 | } |
123 | |||
124 | if (!state->is_cx231xx) { | ||
125 | |||
111 | /* VID_PLL and AUX_PLL */ | 126 | /* VID_PLL and AUX_PLL */ |
112 | cx25840_write4(client, 0x108, 0x1e08040f); | 127 | cx25840_write4(client, 0x108, 0x1e08040f); |
113 | 128 | ||
114 | /* AUX_PLL_FRAC */ | 129 | /* AUX_PLL_FRAC */ |
115 | cx25840_write4(client, 0x110, 0x012a0869); | 130 | cx25840_write4(client, 0x110, 0x012a0869); |
131 | } | ||
116 | 132 | ||
117 | if (state->is_cx25836) | 133 | if (state->is_cx25836) |
118 | break; | 134 | break; |
@@ -136,11 +152,15 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
136 | break; | 152 | break; |
137 | } | 153 | } |
138 | 154 | ||
155 | |||
156 | if (!state->is_cx231xx) { | ||
157 | |||
139 | /* VID_PLL and AUX_PLL */ | 158 | /* VID_PLL and AUX_PLL */ |
140 | cx25840_write4(client, 0x108, 0x1809040f); | 159 | cx25840_write4(client, 0x108, 0x1809040f); |
141 | 160 | ||
142 | /* AUX_PLL_FRAC */ | 161 | /* AUX_PLL_FRAC */ |
143 | cx25840_write4(client, 0x110, 0x00ec6bd6); | 162 | cx25840_write4(client, 0x110, 0x00ec6bd6); |
163 | } | ||
144 | 164 | ||
145 | if (state->is_cx25836) | 165 | if (state->is_cx25836) |
146 | break; | 166 | break; |
@@ -155,7 +175,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
155 | break; | 175 | break; |
156 | 176 | ||
157 | case 48000: | 177 | case 48000: |
158 | if (!state->is_cx23885) { | 178 | if (!state->is_cx23885 && !state->is_cx231xx) { |
159 | /* VID_PLL and AUX_PLL */ | 179 | /* VID_PLL and AUX_PLL */ |
160 | cx25840_write4(client, 0x108, 0x180a040f); | 180 | cx25840_write4(client, 0x108, 0x180a040f); |
161 | 181 | ||
@@ -166,7 +186,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
166 | if (state->is_cx25836) | 186 | if (state->is_cx25836) |
167 | break; | 187 | break; |
168 | 188 | ||
169 | if (!state->is_cx23885) { | 189 | if (!state->is_cx23885 && !state->is_cx231xx) { |
170 | /* src1_ctl */ | 190 | /* src1_ctl */ |
171 | cx25840_write4(client, 0x8f8, 0x08018000); | 191 | cx25840_write4(client, 0x8f8, 0x08018000); |
172 | 192 | ||
@@ -227,7 +247,7 @@ void cx25840_audio_set_path(struct i2c_client *client) | |||
227 | /* deassert soft reset */ | 247 | /* deassert soft reset */ |
228 | cx25840_and_or(client, 0x810, ~0x1, 0x00); | 248 | cx25840_and_or(client, 0x810, ~0x1, 0x00); |
229 | 249 | ||
230 | if (state->is_cx23885) { | 250 | if (state->is_cx23885 || state->is_cx231xx) { |
231 | /* Ensure the controller is running when we exit */ | 251 | /* Ensure the controller is running when we exit */ |
232 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | 252 | cx25840_and_or(client, 0x803, ~0x10, 0x10); |
233 | } | 253 | } |
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 737ee4ea8830..9108f74c0f71 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -345,6 +345,81 @@ static void cx23885_initialize(struct i2c_client *client) | |||
345 | 345 | ||
346 | /* ----------------------------------------------------------------------- */ | 346 | /* ----------------------------------------------------------------------- */ |
347 | 347 | ||
348 | static void cx231xx_initialize(struct i2c_client *client) | ||
349 | { | ||
350 | DEFINE_WAIT(wait); | ||
351 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | ||
352 | struct workqueue_struct *q; | ||
353 | |||
354 | /* Internal Reset */ | ||
355 | cx25840_and_or(client, 0x102, ~0x01, 0x01); | ||
356 | cx25840_and_or(client, 0x102, ~0x01, 0x00); | ||
357 | |||
358 | /* Stop microcontroller */ | ||
359 | cx25840_and_or(client, 0x803, ~0x10, 0x00); | ||
360 | |||
361 | /* DIF in reset? */ | ||
362 | cx25840_write(client, 0x398, 0); | ||
363 | |||
364 | /* Trust the default xtal, no division */ | ||
365 | /* This changes for the cx23888 products */ | ||
366 | cx25840_write(client, 0x2, 0x76); | ||
367 | |||
368 | /* Bring down the regulator for AUX clk */ | ||
369 | cx25840_write(client, 0x1, 0x40); | ||
370 | |||
371 | /* Disable DIF bypass */ | ||
372 | cx25840_write4(client, 0x33c, 0x00000001); | ||
373 | |||
374 | /* DIF Src phase inc */ | ||
375 | cx25840_write4(client, 0x340, 0x0df7df83); | ||
376 | |||
377 | |||
378 | /* Luma */ | ||
379 | cx25840_write4(client, 0x414, 0x00107d12); | ||
380 | |||
381 | /* Chroma */ | ||
382 | cx25840_write4(client, 0x420, 0x3d008282); | ||
383 | |||
384 | |||
385 | |||
386 | /* ADC2 input select */ | ||
387 | cx25840_write(client, 0x102, 0x10); | ||
388 | |||
389 | /* VIN1 & VIN5 */ | ||
390 | cx25840_write(client, 0x103, 0x11); | ||
391 | |||
392 | /* Enable format auto detect */ | ||
393 | cx25840_write(client, 0x400, 0); | ||
394 | /* Fast subchroma lock */ | ||
395 | /* White crush, Chroma AGC & Chroma Killer enabled */ | ||
396 | cx25840_write(client, 0x401, 0xe8); | ||
397 | |||
398 | |||
399 | /* Do the firmware load in a work handler to prevent. | ||
400 | Otherwise the kernel is blocked waiting for the | ||
401 | bit-banging i2c interface to finish uploading the | ||
402 | firmware. */ | ||
403 | INIT_WORK(&state->fw_work, cx25840_work_handler); | ||
404 | init_waitqueue_head(&state->fw_wait); | ||
405 | q = create_singlethread_workqueue("cx25840_fw"); | ||
406 | prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE); | ||
407 | queue_work(q, &state->fw_work); | ||
408 | schedule(); | ||
409 | finish_wait(&state->fw_wait, &wait); | ||
410 | destroy_workqueue(q); | ||
411 | |||
412 | cx25840_std_setup(client); | ||
413 | |||
414 | /* (re)set input */ | ||
415 | set_input(client, state->vid_input, state->aud_input); | ||
416 | |||
417 | /* start microcontroller */ | ||
418 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
419 | } | ||
420 | |||
421 | /* ----------------------------------------------------------------------- */ | ||
422 | |||
348 | void cx25840_std_setup(struct i2c_client *client) | 423 | void cx25840_std_setup(struct i2c_client *client) |
349 | { | 424 | { |
350 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | 425 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
@@ -414,6 +489,7 @@ void cx25840_std_setup(struct i2c_client *client) | |||
414 | } | 489 | } |
415 | 490 | ||
416 | /* DEBUG: Displays configured PLL frequency */ | 491 | /* DEBUG: Displays configured PLL frequency */ |
492 | if (!state->is_cx231xx) { | ||
417 | pll_int = cx25840_read(client, 0x108); | 493 | pll_int = cx25840_read(client, 0x108); |
418 | pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff; | 494 | pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff; |
419 | pll_post = cx25840_read(client, 0x109); | 495 | pll_post = cx25840_read(client, 0x109); |
@@ -448,6 +524,7 @@ void cx25840_std_setup(struct i2c_client *client) | |||
448 | hblank, hactive, vblank, vactive, vblank656, | 524 | hblank, hactive, vblank, vactive, vblank656, |
449 | src_decimation, burst, luma_lpf, uv_lpf, comb, sc); | 525 | src_decimation, burst, luma_lpf, uv_lpf, comb, sc); |
450 | } | 526 | } |
527 | } | ||
451 | 528 | ||
452 | /* Sets horizontal blanking delay and active lines */ | 529 | /* Sets horizontal blanking delay and active lines */ |
453 | cx25840_write(client, 0x470, hblank); | 530 | cx25840_write(client, 0x470, hblank); |
@@ -596,7 +673,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
596 | * configuration in reg (for the cx23885) so we have no | 673 | * configuration in reg (for the cx23885) so we have no |
597 | * need to attempt to flip bits for earlier av decoders. | 674 | * need to attempt to flip bits for earlier av decoders. |
598 | */ | 675 | */ |
599 | if (!state->is_cx23885) { | 676 | if (!state->is_cx23885 && !state->is_cx231xx) { |
600 | switch (aud_input) { | 677 | switch (aud_input) { |
601 | case CX25840_AUDIO_SERIAL: | 678 | case CX25840_AUDIO_SERIAL: |
602 | /* do nothing, use serial audio input */ | 679 | /* do nothing, use serial audio input */ |
@@ -619,7 +696,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
619 | /* Set INPUT_MODE to Composite (0) or S-Video (1) */ | 696 | /* Set INPUT_MODE to Composite (0) or S-Video (1) */ |
620 | cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02); | 697 | cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02); |
621 | 698 | ||
622 | if (!state->is_cx23885) { | 699 | if (!state->is_cx23885 && !state->is_cx231xx) { |
623 | /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ | 700 | /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ |
624 | cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); | 701 | cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); |
625 | /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2&CH3 */ | 702 | /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2&CH3 */ |
@@ -659,6 +736,19 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
659 | */ | 736 | */ |
660 | cx25840_write(client, 0x918, 0xa0); | 737 | cx25840_write(client, 0x918, 0xa0); |
661 | cx25840_write(client, 0x919, 0x01); | 738 | cx25840_write(client, 0x919, 0x01); |
739 | } else if (state->is_cx231xx) { | ||
740 | /* Audio channel 1 src : Parallel 1 */ | ||
741 | cx25840_write(client, 0x124, 0x03); | ||
742 | |||
743 | /* I2S_IN_CTL: I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 */ | ||
744 | cx25840_write(client, 0x914, 0xa0); | ||
745 | |||
746 | /* I2S_OUT_CTL: | ||
747 | * I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 | ||
748 | * I2S_OUT_MASTER_MODE = Master | ||
749 | */ | ||
750 | cx25840_write(client, 0x918, 0xa0); | ||
751 | cx25840_write(client, 0x919, 0x01); | ||
662 | } | 752 | } |
663 | 753 | ||
664 | return 0; | 754 | return 0; |
@@ -719,7 +809,7 @@ static int set_v4lstd(struct i2c_client *client) | |||
719 | 809 | ||
720 | static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 810 | static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
721 | { | 811 | { |
722 | struct cx25840_state *state = to_state(sd); | 812 | struct cx25840_state *state = to_state(sd); |
723 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 813 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
724 | 814 | ||
725 | switch (ctrl->id) { | 815 | switch (ctrl->id) { |
@@ -786,7 +876,7 @@ static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
786 | 876 | ||
787 | static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 877 | static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
788 | { | 878 | { |
789 | struct cx25840_state *state = to_state(sd); | 879 | struct cx25840_state *state = to_state(sd); |
790 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 880 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
791 | 881 | ||
792 | switch (ctrl->id) { | 882 | switch (ctrl->id) { |
@@ -1118,6 +1208,8 @@ static int cx25840_init(struct v4l2_subdev *sd, u32 val) | |||
1118 | cx25836_initialize(client); | 1208 | cx25836_initialize(client); |
1119 | else if (state->is_cx23885) | 1209 | else if (state->is_cx23885) |
1120 | cx23885_initialize(client); | 1210 | cx23885_initialize(client); |
1211 | else if (state->is_cx231xx) | ||
1212 | cx231xx_initialize(client); | ||
1121 | else | 1213 | else |
1122 | cx25840_initialize(client); | 1214 | cx25840_initialize(client); |
1123 | } | 1215 | } |
@@ -1159,7 +1251,7 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) | |||
1159 | v4l_dbg(1, cx25840_debug, client, "%s output\n", | 1251 | v4l_dbg(1, cx25840_debug, client, "%s output\n", |
1160 | enable ? "enable" : "disable"); | 1252 | enable ? "enable" : "disable"); |
1161 | if (enable) { | 1253 | if (enable) { |
1162 | if (state->is_cx23885) { | 1254 | if (state->is_cx23885 || state->is_cx231xx) { |
1163 | u8 v = (cx25840_read(client, 0x421) | 0x0b); | 1255 | u8 v = (cx25840_read(client, 0x421) | 0x0b); |
1164 | cx25840_write(client, 0x421, v); | 1256 | cx25840_write(client, 0x421, v); |
1165 | } else { | 1257 | } else { |
@@ -1169,7 +1261,7 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) | |||
1169 | state->is_cx25836 ? 0x04 : 0x07); | 1261 | state->is_cx25836 ? 0x04 : 0x07); |
1170 | } | 1262 | } |
1171 | } else { | 1263 | } else { |
1172 | if (state->is_cx23885) { | 1264 | if (state->is_cx23885 || state->is_cx231xx) { |
1173 | u8 v = cx25840_read(client, 0x421) & ~(0x0b); | 1265 | u8 v = cx25840_read(client, 0x421) & ~(0x0b); |
1174 | cx25840_write(client, 0x421, v); | 1266 | cx25840_write(client, 0x421, v); |
1175 | } else { | 1267 | } else { |
@@ -1350,6 +1442,8 @@ static int cx25840_reset(struct v4l2_subdev *sd, u32 val) | |||
1350 | cx25836_initialize(client); | 1442 | cx25836_initialize(client); |
1351 | else if (state->is_cx23885) | 1443 | else if (state->is_cx23885) |
1352 | cx23885_initialize(client); | 1444 | cx23885_initialize(client); |
1445 | else if (state->is_cx231xx) | ||
1446 | cx231xx_initialize(client); | ||
1353 | else | 1447 | else |
1354 | cx25840_initialize(client); | 1448 | cx25840_initialize(client); |
1355 | return 0; | 1449 | return 0; |
@@ -1445,10 +1539,12 @@ static int cx25840_probe(struct i2c_client *client, | |||
1445 | } | 1539 | } |
1446 | else if ((device_id & 0xff00) == 0x8400) { | 1540 | else if ((device_id & 0xff00) == 0x8400) { |
1447 | id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); | 1541 | id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); |
1448 | } else if (device_id == 0x0000) { | 1542 | } /* else if (device_id == 0x0000) { |
1449 | id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; | 1543 | id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; |
1450 | } else if (device_id == 0x1313) { | 1544 | } */ else if (device_id == 0x1313) { |
1451 | id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; | 1545 | id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; |
1546 | } else if ((device_id & 0xfff0) == 0x5A30) { | ||
1547 | id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); | ||
1452 | } | 1548 | } |
1453 | else { | 1549 | else { |
1454 | v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); | 1550 | v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); |
@@ -1471,6 +1567,7 @@ static int cx25840_probe(struct i2c_client *client, | |||
1471 | state->c = client; | 1567 | state->c = client; |
1472 | state->is_cx25836 = ((device_id & 0xff00) == 0x8300); | 1568 | state->is_cx25836 = ((device_id & 0xff00) == 0x8300); |
1473 | state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313); | 1569 | state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313); |
1570 | state->is_cx231xx = (device_id == 0x5A3E); | ||
1474 | state->vid_input = CX25840_COMPOSITE7; | 1571 | state->vid_input = CX25840_COMPOSITE7; |
1475 | state->aud_input = CX25840_AUDIO8; | 1572 | state->aud_input = CX25840_AUDIO8; |
1476 | state->audclk_freq = 48000; | 1573 | state->audclk_freq = 48000; |
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h index 9ad0eb86ecfd..814b56536994 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/video/cx25840/cx25840-core.h | |||
@@ -50,6 +50,7 @@ struct cx25840_state { | |||
50 | u32 rev; | 50 | u32 rev; |
51 | int is_cx25836; | 51 | int is_cx25836; |
52 | int is_cx23885; | 52 | int is_cx23885; |
53 | int is_cx231xx; | ||
53 | int is_initialized; | 54 | int is_initialized; |
54 | wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ | 55 | wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ |
55 | struct work_struct fw_work; /* work entry for fw load */ | 56 | struct work_struct fw_work; /* work entry for fw load */ |
diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index 0b2dceb74108..1a5f7d0ead41 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #define FWFILE "v4l-cx25840.fw" | 26 | #define FWFILE "v4l-cx25840.fw" |
27 | #define FWFILE_CX23885 "v4l-cx23885-avcore-01.fw" | 27 | #define FWFILE_CX23885 "v4l-cx23885-avcore-01.fw" |
28 | #define FWFILE_CX231XX "v4l-cx231xx-avcore-01.fw" | ||
28 | 29 | ||
29 | /* | 30 | /* |
30 | * Mike Isely <isely@pobox.com> - The FWSEND parameter controls the | 31 | * Mike Isely <isely@pobox.com> - The FWSEND parameter controls the |
@@ -96,9 +97,17 @@ int cx25840_loadfw(struct i2c_client *client) | |||
96 | u8 buffer[FWSEND]; | 97 | u8 buffer[FWSEND]; |
97 | const u8 *ptr; | 98 | const u8 *ptr; |
98 | int size, retval; | 99 | int size, retval; |
100 | int MAX_BUF_SIZE = FWSEND; | ||
99 | 101 | ||
100 | if (state->is_cx23885) | 102 | if (state->is_cx23885) |
101 | firmware = FWFILE_CX23885; | 103 | firmware = FWFILE_CX23885; |
104 | else if ( state->is_cx231xx) | ||
105 | firmware = FWFILE_CX231XX; | ||
106 | |||
107 | if( (state->is_cx231xx) && MAX_BUF_SIZE > 16) { | ||
108 | printk(" Firmware download size changed to 16 bytes max length\n"); | ||
109 | MAX_BUF_SIZE = 16; /* cx231xx cannot accept more than 16 bytes at a time */ | ||
110 | } | ||
102 | 111 | ||
103 | if (request_firmware(&fw, firmware, FWDEV(client)) != 0) { | 112 | if (request_firmware(&fw, firmware, FWDEV(client)) != 0) { |
104 | v4l_err(client, "unable to open firmware %s\n", firmware); | 113 | v4l_err(client, "unable to open firmware %s\n", firmware); |
@@ -113,7 +122,7 @@ int cx25840_loadfw(struct i2c_client *client) | |||
113 | size = fw->size; | 122 | size = fw->size; |
114 | ptr = fw->data; | 123 | ptr = fw->data; |
115 | while (size > 0) { | 124 | while (size > 0) { |
116 | int len = min(FWSEND - 2, size); | 125 | int len = min(MAX_BUF_SIZE - 2, size); |
117 | 126 | ||
118 | memcpy(buffer + 2, ptr, len); | 127 | memcpy(buffer + 2, ptr, len); |
119 | 128 | ||