aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/saa7115.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/saa7115.c')
-rw-r--r--drivers/media/video/saa7115.c137
1 files changed, 52 insertions, 85 deletions
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index dceebc0b1250..b59c11717273 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -72,6 +72,10 @@ struct saa7115_state {
72 int sat; 72 int sat;
73 enum v4l2_chip_ident ident; 73 enum v4l2_chip_ident ident;
74 u32 audclk_freq; 74 u32 audclk_freq;
75 u32 crystal_freq;
76 u8 ucgc;
77 u8 cgcdiv;
78 u8 apll;
75}; 79};
76 80
77/* ----------------------------------------------------------------------- */ 81/* ----------------------------------------------------------------------- */
@@ -375,10 +379,6 @@ static const unsigned char saa7113_init_auto_input[] = {
375}; 379};
376 380
377static const unsigned char saa7115_init_misc[] = { 381static const unsigned char saa7115_init_misc[] = {
378 0x38, 0x03, /* audio stuff */
379 0x39, 0x10,
380 0x3a, 0x08,
381
382 0x81, 0x01, /* reg 0x15,0x16 define blanking window */ 382 0x81, 0x01, /* reg 0x15,0x16 define blanking window */
383 0x82, 0x00, 383 0x82, 0x00,
384 0x83, 0x01, /* I port settings */ 384 0x83, 0x01, /* I port settings */
@@ -584,6 +584,7 @@ static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
584 u32 acni; 584 u32 acni;
585 u32 hz; 585 u32 hz;
586 u64 f; 586 u64 f;
587 u8 acc = 0; /* reg 0x3a, audio clock control */
587 588
588 v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq); 589 v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq);
589 590
@@ -591,18 +592,34 @@ static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
591 if (freq < 32000 || freq > 48000) 592 if (freq < 32000 || freq > 48000)
592 return -EINVAL; 593 return -EINVAL;
593 594
595 /* The saa7113 has no audio clock */
596 if (state->ident == V4L2_IDENT_SAA7113)
597 return 0;
598
594 /* hz is the refresh rate times 100 */ 599 /* hz is the refresh rate times 100 */
595 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000; 600 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
596 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */ 601 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
597 acpf = (25600 * freq) / hz; 602 acpf = (25600 * freq) / hz;
598 /* acni = (256 * freq * 2^23) / crystal_frequency = 603 /* acni = (256 * freq * 2^23) / crystal_frequency =
599 (freq * 2^(8+23)) / crystal_frequency = 604 (freq * 2^(8+23)) / crystal_frequency =
600 (freq << 31) / 32.11 MHz */ 605 (freq << 31) / crystal_frequency */
601 f = freq; 606 f = freq;
602 f = f << 31; 607 f = f << 31;
603 do_div(f, 32110000); 608 do_div(f, state->crystal_freq);
604 acni = f; 609 acni = f;
610 if (state->ucgc) {
611 acpf = acpf * state->cgcdiv / 16;
612 acni = acni * state->cgcdiv / 16;
613 acc = 0x80;
614 if (state->cgcdiv == 3)
615 acc |= 0x40;
616 }
617 if (state->apll)
618 acc |= 0x08;
605 619
620 saa7115_write(client, 0x38, 0x03);
621 saa7115_write(client, 0x39, 0x10);
622 saa7115_write(client, 0x3a, acc);
606 saa7115_write(client, 0x30, acpf & 0xff); 623 saa7115_write(client, 0x30, acpf & 0xff);
607 saa7115_write(client, 0x31, (acpf >> 8) & 0xff); 624 saa7115_write(client, 0x31, (acpf >> 8) & 0xff);
608 saa7115_write(client, 0x32, (acpf >> 16) & 0x03); 625 saa7115_write(client, 0x32, (acpf >> 16) & 0x03);
@@ -1073,48 +1090,6 @@ static void saa7115_decode_vbi_line(struct i2c_client *client,
1073 1090
1074/* ============ SAA7115 AUDIO settings (end) ============= */ 1091/* ============ SAA7115 AUDIO settings (end) ============= */
1075 1092
1076static struct v4l2_queryctrl saa7115_qctrl[] = {
1077 {
1078 .id = V4L2_CID_BRIGHTNESS,
1079 .type = V4L2_CTRL_TYPE_INTEGER,
1080 .name = "Brightness",
1081 .minimum = 0,
1082 .maximum = 255,
1083 .step = 1,
1084 .default_value = 128,
1085 .flags = 0,
1086 }, {
1087 .id = V4L2_CID_CONTRAST,
1088 .type = V4L2_CTRL_TYPE_INTEGER,
1089 .name = "Contrast",
1090 .minimum = 0,
1091 .maximum = 127,
1092 .step = 1,
1093 .default_value = 64,
1094 .flags = 0,
1095 }, {
1096 .id = V4L2_CID_SATURATION,
1097 .type = V4L2_CTRL_TYPE_INTEGER,
1098 .name = "Saturation",
1099 .minimum = 0,
1100 .maximum = 127,
1101 .step = 1,
1102 .default_value = 64,
1103 .flags = 0,
1104 }, {
1105 .id = V4L2_CID_HUE,
1106 .type = V4L2_CTRL_TYPE_INTEGER,
1107 .name = "Hue",
1108 .minimum = -128,
1109 .maximum = 127,
1110 .step = 1,
1111 .default_value = 0,
1112 .flags = 0,
1113 },
1114};
1115
1116/* ----------------------------------------------------------------------- */
1117
1118static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) 1093static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg)
1119{ 1094{
1120 struct saa7115_state *state = i2c_get_clientdata(client); 1095 struct saa7115_state *state = i2c_get_clientdata(client);
@@ -1158,14 +1133,16 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
1158 case VIDIOC_QUERYCTRL: 1133 case VIDIOC_QUERYCTRL:
1159 { 1134 {
1160 struct v4l2_queryctrl *qc = arg; 1135 struct v4l2_queryctrl *qc = arg;
1161 int i;
1162 1136
1163 for (i = 0; i < ARRAY_SIZE(saa7115_qctrl); i++) 1137 switch (qc->id) {
1164 if (qc->id && qc->id == saa7115_qctrl[i].id) { 1138 case V4L2_CID_BRIGHTNESS:
1165 memcpy(qc, &saa7115_qctrl[i], sizeof(*qc)); 1139 case V4L2_CID_CONTRAST:
1166 return 0; 1140 case V4L2_CID_SATURATION:
1167 } 1141 case V4L2_CID_HUE:
1168 return -EINVAL; 1142 return v4l2_ctrl_query_fill_std(qc);
1143 default:
1144 return -EINVAL;
1145 }
1169 } 1146 }
1170 1147
1171 case VIDIOC_G_STD: 1148 case VIDIOC_G_STD:
@@ -1221,34 +1198,6 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
1221 break; 1198 break;
1222 } 1199 }
1223 1200
1224 case VIDIOC_G_INPUT:
1225 *(int *)arg = state->input;
1226 break;
1227
1228 case VIDIOC_S_INPUT:
1229 v4l_dbg(1, debug, client, "decoder set input %d\n", *iarg);
1230 /* inputs from 0-9 are available */
1231 if (*iarg < 0 || *iarg > 9) {
1232 return -EINVAL;
1233 }
1234
1235 if (state->input == *iarg)
1236 break;
1237 v4l_dbg(1, debug, client, "now setting %s input\n",
1238 *iarg >= 6 ? "S-Video" : "Composite");
1239 state->input = *iarg;
1240
1241 /* select mode */
1242 saa7115_write(client, 0x02,
1243 (saa7115_read(client, 0x02) & 0xf0) |
1244 state->input);
1245
1246 /* bypass chrominance trap for modes 6..9 */
1247 saa7115_write(client, 0x09,
1248 (saa7115_read(client, 0x09) & 0x7f) |
1249 (state->input < 6 ? 0x0 : 0x80));
1250 break;
1251
1252 case VIDIOC_STREAMON: 1201 case VIDIOC_STREAMON:
1253 case VIDIOC_STREAMOFF: 1202 case VIDIOC_STREAMOFF:
1254 v4l_dbg(1, debug, client, "%s output\n", 1203 v4l_dbg(1, debug, client, "%s output\n",
@@ -1260,6 +1209,21 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
1260 } 1209 }
1261 break; 1210 break;
1262 1211
1212 case VIDIOC_INT_S_CRYSTAL_FREQ:
1213 {
1214 struct v4l2_crystal_freq *freq = arg;
1215
1216 if (freq->freq != SAA7115_FREQ_32_11_MHZ &&
1217 freq->freq != SAA7115_FREQ_24_576_MHZ)
1218 return -EINVAL;
1219 state->crystal_freq = freq->freq;
1220 state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
1221 state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
1222 state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
1223 saa7115_set_audio_clock_freq(client, state->audclk_freq);
1224 break;
1225 }
1226
1263 case VIDIOC_INT_DECODE_VBI_LINE: 1227 case VIDIOC_INT_DECODE_VBI_LINE:
1264 saa7115_decode_vbi_line(client, arg); 1228 saa7115_decode_vbi_line(client, arg);
1265 break; 1229 break;
@@ -1401,10 +1365,13 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
1401 v4l_dbg(1, debug, client, "writing init values\n"); 1365 v4l_dbg(1, debug, client, "writing init values\n");
1402 1366
1403 /* init to 60hz/48khz */ 1367 /* init to 60hz/48khz */
1404 if (state->ident == V4L2_IDENT_SAA7113) 1368 if (state->ident == V4L2_IDENT_SAA7113) {
1369 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
1405 saa7115_writeregs(client, saa7113_init_auto_input); 1370 saa7115_writeregs(client, saa7113_init_auto_input);
1406 else 1371 } else {
1372 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
1407 saa7115_writeregs(client, saa7115_init_auto_input); 1373 saa7115_writeregs(client, saa7115_init_auto_input);
1374 }
1408 saa7115_writeregs(client, saa7115_init_misc); 1375 saa7115_writeregs(client, saa7115_init_misc);
1409 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); 1376 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
1410 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); 1377 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);