aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx25840/cx25840-core.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2006-04-22 09:22:46 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-06-25 01:00:16 -0400
commite2b8cf4ced47465b24d6fe911714827475fb0412 (patch)
treeadc3dcf673c084ad58f3ace0c11d44141cd892a4 /drivers/media/video/cx25840/cx25840-core.c
parent3eb731705556b643df2cbae1bc98976335451548 (diff)
V4L/DVB (4005): Add support for the cx25836/7 video decoder.
Signed-off-by: Scott Alfter <salfter@ssai.us> Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/cx25840/cx25840-core.c')
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c181
1 files changed, 128 insertions, 53 deletions
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index a961bb2ab0fd..e4655e3c2520 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -105,7 +105,7 @@ u32 cx25840_read4(struct i2c_client * client, u16 addr)
105 (buffer[2] << 8) | buffer[3]; 105 (buffer[2] << 8) | buffer[3];
106} 106}
107 107
108int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask, 108int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask,
109 u8 or_value) 109 u8 or_value)
110{ 110{
111 return cx25840_write(client, addr, 111 return cx25840_write(client, addr,
@@ -117,7 +117,8 @@ int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask,
117 117
118static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, 118static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
119 enum cx25840_audio_input aud_input); 119 enum cx25840_audio_input aud_input);
120static void log_status(struct i2c_client *client); 120static void log_audio_status(struct i2c_client *client);
121static void log_video_status(struct i2c_client *client);
121 122
122/* ----------------------------------------------------------------------- */ 123/* ----------------------------------------------------------------------- */
123 124
@@ -147,6 +148,33 @@ static void init_dll2(struct i2c_client *client)
147 cx25840_write(client, 0x15d, 0xe1); 148 cx25840_write(client, 0x15d, 0xe1);
148} 149}
149 150
151static void cx25836_initialize(struct i2c_client *client)
152{
153 /* reset configuration is described on page 3-77 of the CX25836 datasheet */
154 /* 2. */
155 cx25840_and_or(client, 0x000, ~0x01, 0x01);
156 cx25840_and_or(client, 0x000, ~0x01, 0x00);
157 /* 3a. */
158 cx25840_and_or(client, 0x15a, ~0x70, 0x00);
159 /* 3b. */
160 cx25840_and_or(client, 0x15b, ~0x1e, 0x06);
161 /* 3c. */
162 cx25840_and_or(client, 0x159, ~0x02, 0x02);
163 /* 3d. */
164 /* There should be a 10-us delay here, but since the
165 i2c bus already has a 10-us delay we don't need to do
166 anything */
167 /* 3e. */
168 cx25840_and_or(client, 0x159, ~0x02, 0x00);
169 /* 3f. */
170 cx25840_and_or(client, 0x159, ~0xc0, 0xc0);
171 /* 3g. */
172 cx25840_and_or(client, 0x159, ~0x01, 0x00);
173 cx25840_and_or(client, 0x159, ~0x01, 0x01);
174 /* 3h. */
175 cx25840_and_or(client, 0x15b, ~0x1e, 0x10);
176}
177
150static void cx25840_initialize(struct i2c_client *client, int loadfw) 178static void cx25840_initialize(struct i2c_client *client, int loadfw)
151{ 179{
152 struct cx25840_state *state = i2c_get_clientdata(client); 180 struct cx25840_state *state = i2c_get_clientdata(client);
@@ -319,8 +347,10 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
319 347
320 state->vid_input = vid_input; 348 state->vid_input = vid_input;
321 state->aud_input = aud_input; 349 state->aud_input = aud_input;
322 cx25840_audio_set_path(client); 350 if (!state->is_cx25836) {
323 input_change(client); 351 cx25840_audio_set_path(client);
352 input_change(client);
353 }
324 return 0; 354 return 0;
325} 355}
326 356
@@ -370,6 +400,7 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
370 400
371v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) 401v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
372{ 402{
403 struct cx25840_state *state = i2c_get_clientdata(client);
373 /* check VID_FMT_SEL first */ 404 /* check VID_FMT_SEL first */
374 u8 fmt = cx25840_read(client, 0x400) & 0xf; 405 u8 fmt = cx25840_read(client, 0x400) & 0xf;
375 406
@@ -383,7 +414,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
383 { 414 {
384 /* if the audio std is A2-M, then this is the South Korean 415 /* if the audio std is A2-M, then this is the South Korean
385 NTSC standard */ 416 NTSC standard */
386 if (cx25840_read(client, 0x805) == 2) 417 if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2)
387 return V4L2_STD_NTSC_M_KR; 418 return V4L2_STD_NTSC_M_KR;
388 return V4L2_STD_NTSC_M; 419 return V4L2_STD_NTSC_M;
389 } 420 }
@@ -456,6 +487,8 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
456 case V4L2_CID_AUDIO_TREBLE: 487 case V4L2_CID_AUDIO_TREBLE:
457 case V4L2_CID_AUDIO_BALANCE: 488 case V4L2_CID_AUDIO_BALANCE:
458 case V4L2_CID_AUDIO_MUTE: 489 case V4L2_CID_AUDIO_MUTE:
490 if (state->is_cx25836)
491 return -EINVAL;
459 return cx25840_audio(client, VIDIOC_S_CTRL, ctrl); 492 return cx25840_audio(client, VIDIOC_S_CTRL, ctrl);
460 493
461 default: 494 default:
@@ -490,6 +523,8 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
490 case V4L2_CID_AUDIO_TREBLE: 523 case V4L2_CID_AUDIO_TREBLE:
491 case V4L2_CID_AUDIO_BALANCE: 524 case V4L2_CID_AUDIO_BALANCE:
492 case V4L2_CID_AUDIO_MUTE: 525 case V4L2_CID_AUDIO_MUTE:
526 if (state->is_cx25836)
527 return -EINVAL;
493 return cx25840_audio(client, VIDIOC_G_CTRL, ctrl); 528 return cx25840_audio(client, VIDIOC_G_CTRL, ctrl);
494 default: 529 default:
495 return -EINVAL; 530 return -EINVAL;
@@ -579,7 +614,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
579 614
580/* ----------------------------------------------------------------------- */ 615/* ----------------------------------------------------------------------- */
581 616
582static struct v4l2_queryctrl cx25840_qctrl[] = { 617static struct v4l2_queryctrl cx25836_qctrl[] = {
583 { 618 {
584 .id = V4L2_CID_BRIGHTNESS, 619 .id = V4L2_CID_BRIGHTNESS,
585 .type = V4L2_CTRL_TYPE_INTEGER, 620 .type = V4L2_CTRL_TYPE_INTEGER,
@@ -616,7 +651,11 @@ static struct v4l2_queryctrl cx25840_qctrl[] = {
616 .step = 1, 651 .step = 1,
617 .default_value = 0, 652 .default_value = 0,
618 .flags = 0, 653 .flags = 0,
619 }, { 654 },
655};
656
657static struct v4l2_queryctrl cx25840_qctrl[] = {
658 {
620 .id = V4L2_CID_AUDIO_VOLUME, 659 .id = V4L2_CID_AUDIO_VOLUME,
621 .type = V4L2_CTRL_TYPE_INTEGER, 660 .type = V4L2_CTRL_TYPE_INTEGER,
622 .name = "Volume", 661 .name = "Volume",
@@ -706,8 +745,8 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
706 745
707 case VIDIOC_STREAMON: 746 case VIDIOC_STREAMON:
708 v4l_dbg(1, cx25840_debug, client, "enable output\n"); 747 v4l_dbg(1, cx25840_debug, client, "enable output\n");
709 cx25840_write(client, 0x115, 0x8c); 748 cx25840_write(client, 0x115, state->is_cx25836 ? 0x0c : 0x8c);
710 cx25840_write(client, 0x116, 0x07); 749 cx25840_write(client, 0x116, state->is_cx25836 ? 0x04 : 0x07);
711 break; 750 break;
712 751
713 case VIDIOC_STREAMOFF: 752 case VIDIOC_STREAMOFF:
@@ -717,7 +756,9 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
717 break; 756 break;
718 757
719 case VIDIOC_LOG_STATUS: 758 case VIDIOC_LOG_STATUS:
720 log_status(client); 759 log_video_status(client);
760 if (!state->is_cx25836)
761 log_audio_status(client);
721 break; 762 break;
722 763
723 case VIDIOC_G_CTRL: 764 case VIDIOC_G_CTRL:
@@ -731,6 +772,14 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
731 struct v4l2_queryctrl *qc = arg; 772 struct v4l2_queryctrl *qc = arg;
732 int i; 773 int i;
733 774
775 for (i = 0; i < ARRAY_SIZE(cx25836_qctrl); i++)
776 if (qc->id && qc->id == cx25836_qctrl[i].id) {
777 memcpy(qc, &cx25836_qctrl[i], sizeof(*qc));
778 return 0;
779 }
780 if (state->is_cx25836)
781 return -EINVAL;
782
734 for (i = 0; i < ARRAY_SIZE(cx25840_qctrl); i++) 783 for (i = 0; i < ARRAY_SIZE(cx25840_qctrl); i++)
735 if (qc->id && qc->id == cx25840_qctrl[i].id) { 784 if (qc->id && qc->id == cx25840_qctrl[i].id) {
736 memcpy(qc, &cx25840_qctrl[i], sizeof(*qc)); 785 memcpy(qc, &cx25840_qctrl[i], sizeof(*qc));
@@ -760,31 +809,41 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
760 return set_input(client, route->input, state->aud_input); 809 return set_input(client, route->input, state->aud_input);
761 810
762 case VIDIOC_INT_G_AUDIO_ROUTING: 811 case VIDIOC_INT_G_AUDIO_ROUTING:
812 if (state->is_cx25836)
813 return -EINVAL;
763 route->input = state->aud_input; 814 route->input = state->aud_input;
764 route->output = 0; 815 route->output = 0;
765 break; 816 break;
766 817
767 case VIDIOC_INT_S_AUDIO_ROUTING: 818 case VIDIOC_INT_S_AUDIO_ROUTING:
819 if (state->is_cx25836)
820 return -EINVAL;
768 return set_input(client, state->vid_input, route->input); 821 return set_input(client, state->vid_input, route->input);
769 822
770 case VIDIOC_S_FREQUENCY: 823 case VIDIOC_S_FREQUENCY:
771 input_change(client); 824 if (!state->is_cx25836) {
825 input_change(client);
826 }
772 break; 827 break;
773 828
774 case VIDIOC_G_TUNER: 829 case VIDIOC_G_TUNER:
775 { 830 {
776 u8 mode = cx25840_read(client, 0x804); 831 u8 vpres = cx25840_read(client, 0x40e) & 0x20;
777 u8 vpres = cx25840_read(client, 0x80a) & 0x10; 832 u8 mode;
778 int val = 0; 833 int val = 0;
779 834
780 if (state->radio) 835 if (state->radio)
781 break; 836 break;
782 837
838 vt->signal = vpres ? 0xffff : 0x0;
839 if (state->is_cx25836)
840 break;
841
783 vt->capability |= 842 vt->capability |=
784 V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | 843 V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
785 V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; 844 V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
786 845
787 vt->signal = vpres ? 0xffff : 0x0; 846 mode = cx25840_read(client, 0x804);
788 847
789 /* get rxsubchans and audmode */ 848 /* get rxsubchans and audmode */
790 if ((mode & 0xf) == 1) 849 if ((mode & 0xf) == 1)
@@ -804,7 +863,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
804 } 863 }
805 864
806 case VIDIOC_S_TUNER: 865 case VIDIOC_S_TUNER:
807 if (state->radio) 866 if (state->radio || state->is_cx25836)
808 break; 867 break;
809 868
810 switch (vt->audmode) { 869 switch (vt->audmode) {
@@ -846,12 +905,14 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
846 return set_v4lfmt(client, (struct v4l2_format *)arg); 905 return set_v4lfmt(client, (struct v4l2_format *)arg);
847 906
848 case VIDIOC_INT_RESET: 907 case VIDIOC_INT_RESET:
849 cx25840_initialize(client, 0); 908 if (state->is_cx25836)
909 cx25836_initialize(client);
910 else
911 cx25840_initialize(client, 0);
850 break; 912 break;
851 913
852 case VIDIOC_INT_G_CHIP_IDENT: 914 case VIDIOC_INT_G_CHIP_IDENT:
853 *(enum v4l2_chip_ident *)arg = 915 *(enum v4l2_chip_ident *)arg = state->id;
854 V4L2_IDENT_CX25840 + ((cx25840_read(client, 0x100) >> 4) & 0xf);
855 break; 916 break;
856 917
857 default: 918 default:
@@ -870,6 +931,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
870{ 931{
871 struct i2c_client *client; 932 struct i2c_client *client;
872 struct cx25840_state *state; 933 struct cx25840_state *state;
934 enum v4l2_chip_ident id;
873 u16 device_id; 935 u16 device_id;
874 936
875 /* Check if the adapter supports the needed features 937 /* Check if the adapter supports the needed features
@@ -878,10 +940,11 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
878 if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) 940 if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
879 return 0; 941 return 0;
880 942
881 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); 943 state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL);
882 if (client == 0) 944 if (state == 0)
883 return -ENOMEM; 945 return -ENOMEM;
884 946
947 client = &state->c;
885 client->addr = address; 948 client->addr = address;
886 client->adapter = adapter; 949 client->adapter = adapter;
887 client->driver = &i2c_driver_cx25840; 950 client->driver = &i2c_driver_cx25840;
@@ -893,10 +956,18 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
893 device_id |= cx25840_read(client, 0x100); 956 device_id |= cx25840_read(client, 0x100);
894 957
895 /* The high byte of the device ID should be 958 /* The high byte of the device ID should be
896 * 0x84 if chip is present */ 959 * 0x83 for the cx2583x and 0x84 for the cx2584x */
897 if ((device_id & 0xff00) != 0x8400) { 960 if ((device_id & 0xff00) == 0x8300) {
961 id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6;
962 state->is_cx25836 = 1;
963 }
964 else if ((device_id & 0xff00) == 0x8400) {
965 id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf);
966 state->is_cx25836 = 0;
967 }
968 else {
898 v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); 969 v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n");
899 kfree(client); 970 kfree(state);
900 return 0; 971 return 0;
901 } 972 }
902 973
@@ -905,21 +976,18 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
905 (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3, 976 (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3,
906 address << 1, adapter->name); 977 address << 1, adapter->name);
907 978
908 state = kmalloc(sizeof(struct cx25840_state), GFP_KERNEL);
909 if (state == NULL) {
910 kfree(client);
911 return -ENOMEM;
912 }
913
914 i2c_set_clientdata(client, state); 979 i2c_set_clientdata(client, state);
915 memset(state, 0, sizeof(struct cx25840_state));
916 state->vid_input = CX25840_COMPOSITE7; 980 state->vid_input = CX25840_COMPOSITE7;
917 state->aud_input = CX25840_AUDIO8; 981 state->aud_input = CX25840_AUDIO8;
918 state->audclk_freq = 48000; 982 state->audclk_freq = 48000;
919 state->pvr150_workaround = 0; 983 state->pvr150_workaround = 0;
920 state->audmode = V4L2_TUNER_MODE_LANG1; 984 state->audmode = V4L2_TUNER_MODE_LANG1;
985 state->id = id;
921 986
922 cx25840_initialize(client, 1); 987 if (state->is_cx25836)
988 cx25836_initialize(client);
989 else
990 cx25840_initialize(client, 1);
923 991
924 i2c_attach_client(client); 992 i2c_attach_client(client);
925 993
@@ -944,7 +1012,6 @@ static int cx25840_detach_client(struct i2c_client *client)
944 } 1012 }
945 1013
946 kfree(state); 1014 kfree(state);
947 kfree(client);
948 1015
949 return 0; 1016 return 0;
950} 1017}
@@ -977,7 +1044,7 @@ module_exit(m__exit);
977 1044
978/* ----------------------------------------------------------------------- */ 1045/* ----------------------------------------------------------------------- */
979 1046
980static void log_status(struct i2c_client *client) 1047static void log_video_status(struct i2c_client *client)
981{ 1048{
982 static const char *const fmt_strs[] = { 1049 static const char *const fmt_strs[] = {
983 "0x0", 1050 "0x0",
@@ -989,9 +1056,36 @@ static void log_status(struct i2c_client *client)
989 }; 1056 };
990 1057
991 struct cx25840_state *state = i2c_get_clientdata(client); 1058 struct cx25840_state *state = i2c_get_clientdata(client);
992 u8 microctrl_vidfmt = cx25840_read(client, 0x80a);
993 u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf; 1059 u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf;
994 u8 gen_stat1 = cx25840_read(client, 0x40d); 1060 u8 gen_stat1 = cx25840_read(client, 0x40d);
1061 u8 gen_stat2 = cx25840_read(client, 0x40e);
1062 int vid_input = state->vid_input;
1063
1064 v4l_info(client, "Video signal: %spresent\n",
1065 (gen_stat2 & 0x20) ? "" : "not ");
1066 v4l_info(client, "Detected format: %s\n",
1067 fmt_strs[gen_stat1 & 0xf]);
1068
1069 v4l_info(client, "Specified standard: %s\n",
1070 vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
1071
1072 if (vid_input >= CX25840_COMPOSITE1 &&
1073 vid_input <= CX25840_COMPOSITE8) {
1074 v4l_info(client, "Specified video input: Composite %d\n",
1075 vid_input - CX25840_COMPOSITE1 + 1);
1076 } else {
1077 v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n",
1078 (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
1079 }
1080
1081 v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq);
1082}
1083
1084/* ----------------------------------------------------------------------- */
1085
1086static void log_audio_status(struct i2c_client *client)
1087{
1088 struct cx25840_state *state = i2c_get_clientdata(client);
995 u8 download_ctl = cx25840_read(client, 0x803); 1089 u8 download_ctl = cx25840_read(client, 0x803);
996 u8 mod_det_stat0 = cx25840_read(client, 0x804); 1090 u8 mod_det_stat0 = cx25840_read(client, 0x804);
997 u8 mod_det_stat1 = cx25840_read(client, 0x805); 1091 u8 mod_det_stat1 = cx25840_read(client, 0x805);
@@ -999,15 +1093,9 @@ static void log_status(struct i2c_client *client)
999 u8 pref_mode = cx25840_read(client, 0x809); 1093 u8 pref_mode = cx25840_read(client, 0x809);
1000 u8 afc0 = cx25840_read(client, 0x80b); 1094 u8 afc0 = cx25840_read(client, 0x80b);
1001 u8 mute_ctl = cx25840_read(client, 0x8d3); 1095 u8 mute_ctl = cx25840_read(client, 0x8d3);
1002 int vid_input = state->vid_input;
1003 int aud_input = state->aud_input; 1096 int aud_input = state->aud_input;
1004 char *p; 1097 char *p;
1005 1098
1006 v4l_info(client, "Video signal: %spresent\n",
1007 (microctrl_vidfmt & 0x10) ? "" : "not ");
1008 v4l_info(client, "Detected format: %s\n",
1009 fmt_strs[gen_stat1 & 0xf]);
1010
1011 switch (mod_det_stat0) { 1099 switch (mod_det_stat0) {
1012 case 0x00: p = "mono"; break; 1100 case 0x00: p = "mono"; break;
1013 case 0x01: p = "stereo"; break; 1101 case 0x01: p = "stereo"; break;
@@ -1107,25 +1195,12 @@ static void log_status(struct i2c_client *client)
1107 v4l_info(client, "Configured audio system: %s\n", p); 1195 v4l_info(client, "Configured audio system: %s\n", p);
1108 } 1196 }
1109 1197
1110 v4l_info(client, "Specified standard: %s\n",
1111 vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
1112
1113 if (vid_input >= CX25840_COMPOSITE1 &&
1114 vid_input <= CX25840_COMPOSITE8) {
1115 v4l_info(client, "Specified video input: Composite %d\n",
1116 vid_input - CX25840_COMPOSITE1 + 1);
1117 } else {
1118 v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n",
1119 (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
1120 }
1121 if (aud_input) { 1198 if (aud_input) {
1122 v4l_info(client, "Specified audio input: Tuner (In%d)\n", aud_input); 1199 v4l_info(client, "Specified audio input: Tuner (In%d)\n", aud_input);
1123 } else { 1200 } else {
1124 v4l_info(client, "Specified audio input: External\n"); 1201 v4l_info(client, "Specified audio input: External\n");
1125 } 1202 }
1126 1203
1127 v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq);
1128
1129 switch (pref_mode & 0xf) { 1204 switch (pref_mode & 0xf) {
1130 case 0: p = "mono/language A"; break; 1205 case 0: p = "mono/language A"; break;
1131 case 1: p = "language B"; break; 1206 case 1: p = "language B"; break;