0001
0002
0003
0004
0005
0006
0007 #include "pvrusb2-std.h"
0008 #include "pvrusb2-debug.h"
0009 #include <asm/string.h>
0010 #include <linux/slab.h>
0011
0012 struct std_name {
0013 const char *name;
0014 v4l2_std_id id;
0015 };
0016
0017
0018 #define CSTD_PAL \
0019 (V4L2_STD_PAL_B| \
0020 V4L2_STD_PAL_B1| \
0021 V4L2_STD_PAL_G| \
0022 V4L2_STD_PAL_H| \
0023 V4L2_STD_PAL_I| \
0024 V4L2_STD_PAL_D| \
0025 V4L2_STD_PAL_D1| \
0026 V4L2_STD_PAL_K| \
0027 V4L2_STD_PAL_M| \
0028 V4L2_STD_PAL_N| \
0029 V4L2_STD_PAL_Nc| \
0030 V4L2_STD_PAL_60)
0031
0032 #define CSTD_NTSC \
0033 (V4L2_STD_NTSC_M| \
0034 V4L2_STD_NTSC_M_JP| \
0035 V4L2_STD_NTSC_M_KR| \
0036 V4L2_STD_NTSC_443)
0037
0038 #define CSTD_ATSC \
0039 (V4L2_STD_ATSC_8_VSB| \
0040 V4L2_STD_ATSC_16_VSB)
0041
0042 #define CSTD_SECAM \
0043 (V4L2_STD_SECAM_B| \
0044 V4L2_STD_SECAM_D| \
0045 V4L2_STD_SECAM_G| \
0046 V4L2_STD_SECAM_H| \
0047 V4L2_STD_SECAM_K| \
0048 V4L2_STD_SECAM_K1| \
0049 V4L2_STD_SECAM_L| \
0050 V4L2_STD_SECAM_LC)
0051
0052 #define TSTD_B (V4L2_STD_PAL_B|V4L2_STD_SECAM_B)
0053 #define TSTD_B1 (V4L2_STD_PAL_B1)
0054 #define TSTD_D (V4L2_STD_PAL_D|V4L2_STD_SECAM_D)
0055 #define TSTD_D1 (V4L2_STD_PAL_D1)
0056 #define TSTD_G (V4L2_STD_PAL_G|V4L2_STD_SECAM_G)
0057 #define TSTD_H (V4L2_STD_PAL_H|V4L2_STD_SECAM_H)
0058 #define TSTD_I (V4L2_STD_PAL_I)
0059 #define TSTD_K (V4L2_STD_PAL_K|V4L2_STD_SECAM_K)
0060 #define TSTD_K1 (V4L2_STD_SECAM_K1)
0061 #define TSTD_L (V4L2_STD_SECAM_L)
0062 #define TSTD_M (V4L2_STD_PAL_M|V4L2_STD_NTSC_M)
0063 #define TSTD_N (V4L2_STD_PAL_N)
0064 #define TSTD_Nc (V4L2_STD_PAL_Nc)
0065 #define TSTD_60 (V4L2_STD_PAL_60)
0066
0067 #define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_ATSC|CSTD_SECAM)
0068
0069
0070 static const struct std_name std_groups[] = {
0071 {"PAL",CSTD_PAL},
0072 {"NTSC",CSTD_NTSC},
0073 {"SECAM",CSTD_SECAM},
0074 {"ATSC",CSTD_ATSC},
0075 };
0076
0077
0078 static const struct std_name std_items[] = {
0079 {"B",TSTD_B},
0080 {"B1",TSTD_B1},
0081 {"D",TSTD_D},
0082 {"D1",TSTD_D1},
0083 {"G",TSTD_G},
0084 {"H",TSTD_H},
0085 {"I",TSTD_I},
0086 {"K",TSTD_K},
0087 {"K1",TSTD_K1},
0088 {"L",TSTD_L},
0089 {"LC",V4L2_STD_SECAM_LC},
0090 {"M",TSTD_M},
0091 {"Mj",V4L2_STD_NTSC_M_JP},
0092 {"443",V4L2_STD_NTSC_443},
0093 {"Mk",V4L2_STD_NTSC_M_KR},
0094 {"N",TSTD_N},
0095 {"Nc",TSTD_Nc},
0096 {"60",TSTD_60},
0097 {"8VSB",V4L2_STD_ATSC_8_VSB},
0098 {"16VSB",V4L2_STD_ATSC_16_VSB},
0099 };
0100
0101
0102
0103
0104 static const struct std_name *find_std_name(const struct std_name *arrPtr,
0105 unsigned int arrSize,
0106 const char *bufPtr,
0107 unsigned int bufSize)
0108 {
0109 unsigned int idx;
0110 const struct std_name *p;
0111 for (idx = 0; idx < arrSize; idx++) {
0112 p = arrPtr + idx;
0113 if (strlen(p->name) != bufSize) continue;
0114 if (!memcmp(bufPtr,p->name,bufSize)) return p;
0115 }
0116 return NULL;
0117 }
0118
0119
0120 int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
0121 unsigned int bufSize)
0122 {
0123 v4l2_std_id id = 0;
0124 v4l2_std_id cmsk = 0;
0125 v4l2_std_id t;
0126 int mMode = 0;
0127 unsigned int cnt;
0128 char ch;
0129 const struct std_name *sp;
0130
0131 while (bufSize) {
0132 if (!mMode) {
0133 cnt = 0;
0134 while ((cnt < bufSize) && (bufPtr[cnt] != '-')) cnt++;
0135 if (cnt >= bufSize) return 0;
0136 sp = find_std_name(std_groups, ARRAY_SIZE(std_groups),
0137 bufPtr,cnt);
0138 if (!sp) return 0;
0139 cnt++;
0140 bufPtr += cnt;
0141 bufSize -= cnt;
0142 mMode = !0;
0143 cmsk = sp->id;
0144 continue;
0145 }
0146 cnt = 0;
0147 while (cnt < bufSize) {
0148 ch = bufPtr[cnt];
0149 if (ch == ';') {
0150 mMode = 0;
0151 break;
0152 }
0153 if (ch == '/') break;
0154 cnt++;
0155 }
0156 sp = find_std_name(std_items, ARRAY_SIZE(std_items),
0157 bufPtr,cnt);
0158 if (!sp) return 0;
0159 t = sp->id & cmsk;
0160 if (!t) return 0;
0161 id |= t;
0162 if (cnt < bufSize) cnt++;
0163 bufPtr += cnt;
0164 bufSize -= cnt;
0165 }
0166
0167 if (idPtr) *idPtr = id;
0168 return !0;
0169 }
0170
0171
0172 unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
0173 v4l2_std_id id)
0174 {
0175 unsigned int idx1,idx2;
0176 const struct std_name *ip,*gp;
0177 int gfl,cfl;
0178 unsigned int c1,c2;
0179 cfl = 0;
0180 c1 = 0;
0181 for (idx1 = 0; idx1 < ARRAY_SIZE(std_groups); idx1++) {
0182 gp = std_groups + idx1;
0183 gfl = 0;
0184 for (idx2 = 0; idx2 < ARRAY_SIZE(std_items); idx2++) {
0185 ip = std_items + idx2;
0186 if (!(gp->id & ip->id & id)) continue;
0187 if (!gfl) {
0188 if (cfl) {
0189 c2 = scnprintf(bufPtr,bufSize,";");
0190 c1 += c2;
0191 bufSize -= c2;
0192 bufPtr += c2;
0193 }
0194 cfl = !0;
0195 c2 = scnprintf(bufPtr,bufSize,
0196 "%s-",gp->name);
0197 gfl = !0;
0198 } else {
0199 c2 = scnprintf(bufPtr,bufSize,"/");
0200 }
0201 c1 += c2;
0202 bufSize -= c2;
0203 bufPtr += c2;
0204 c2 = scnprintf(bufPtr,bufSize,
0205 ip->name);
0206 c1 += c2;
0207 bufSize -= c2;
0208 bufPtr += c2;
0209 }
0210 }
0211 return c1;
0212 }
0213
0214
0215
0216
0217 static struct v4l2_standard generic_standards[] = {
0218 {
0219 .id = (TSTD_B|TSTD_B1|
0220 TSTD_D|TSTD_D1|
0221 TSTD_G|
0222 TSTD_H|
0223 TSTD_I|
0224 TSTD_K|TSTD_K1|
0225 TSTD_L|
0226 V4L2_STD_SECAM_LC |
0227 TSTD_N|TSTD_Nc),
0228 .frameperiod =
0229 {
0230 .numerator = 1,
0231 .denominator= 25
0232 },
0233 .framelines = 625,
0234 .reserved = {0,0,0,0}
0235 }, {
0236 .id = (TSTD_M|
0237 V4L2_STD_NTSC_M_JP|
0238 V4L2_STD_NTSC_M_KR),
0239 .frameperiod =
0240 {
0241 .numerator = 1001,
0242 .denominator= 30000
0243 },
0244 .framelines = 525,
0245 .reserved = {0,0,0,0}
0246 }, {
0247 .id = (TSTD_60),
0248 .frameperiod =
0249 {
0250 .numerator = 1001,
0251 .denominator= 30000
0252 },
0253 .framelines = 525,
0254 .reserved = {0,0,0,0}
0255 }, {
0256 .id = V4L2_STD_NTSC_443,
0257 .frameperiod =
0258 {
0259 .numerator = 1001,
0260 .denominator= 30000
0261 },
0262 .framelines = 525,
0263 .reserved = {0,0,0,0}
0264 }
0265 };
0266
0267 static struct v4l2_standard *match_std(v4l2_std_id id)
0268 {
0269 unsigned int idx;
0270 for (idx = 0; idx < ARRAY_SIZE(generic_standards); idx++) {
0271 if (generic_standards[idx].id & id) {
0272 return generic_standards + idx;
0273 }
0274 }
0275 return NULL;
0276 }
0277
0278 static int pvr2_std_fill(struct v4l2_standard *std,v4l2_std_id id)
0279 {
0280 struct v4l2_standard *template;
0281 int idx;
0282 unsigned int bcnt;
0283 template = match_std(id);
0284 if (!template) return 0;
0285 idx = std->index;
0286 memcpy(std,template,sizeof(*template));
0287 std->index = idx;
0288 std->id = id;
0289 bcnt = pvr2_std_id_to_str(std->name,sizeof(std->name)-1,id);
0290 std->name[bcnt] = 0;
0291 pvr2_trace(PVR2_TRACE_STD,"Set up standard idx=%u name=%s",
0292 std->index,std->name);
0293 return !0;
0294 }
0295
0296
0297
0298 static v4l2_std_id std_mixes[] = {
0299 V4L2_STD_PAL_B | V4L2_STD_PAL_G,
0300 V4L2_STD_PAL_D | V4L2_STD_PAL_K,
0301 V4L2_STD_SECAM_B | V4L2_STD_SECAM_G,
0302 V4L2_STD_SECAM_D | V4L2_STD_SECAM_K,
0303 };
0304
0305 struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
0306 v4l2_std_id id)
0307 {
0308 unsigned int std_cnt = 0;
0309 unsigned int idx,bcnt,idx2;
0310 v4l2_std_id idmsk,cmsk,fmsk;
0311 struct v4l2_standard *stddefs;
0312
0313 if (pvrusb2_debug & PVR2_TRACE_STD) {
0314 char buf[100];
0315 bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id);
0316 pvr2_trace(
0317 PVR2_TRACE_STD,"Mapping standards mask=0x%x (%.*s)",
0318 (int)id,bcnt,buf);
0319 }
0320
0321 *countptr = 0;
0322 std_cnt = 0;
0323 fmsk = 0;
0324 for (idmsk = 1, cmsk = id; cmsk; idmsk <<= 1) {
0325 if (!(idmsk & cmsk)) continue;
0326 cmsk &= ~idmsk;
0327 if (match_std(idmsk)) {
0328 std_cnt++;
0329 continue;
0330 }
0331 fmsk |= idmsk;
0332 }
0333
0334 for (idx2 = 0; idx2 < ARRAY_SIZE(std_mixes); idx2++) {
0335 if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++;
0336 }
0337
0338
0339 fmsk &= ~CSTD_ATSC;
0340
0341 if (fmsk) {
0342 char buf[100];
0343 bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk);
0344 pvr2_trace(
0345 PVR2_TRACE_ERROR_LEGS,
0346 "***WARNING*** Failed to classify the following standard(s): %.*s",
0347 bcnt,buf);
0348 }
0349
0350 pvr2_trace(PVR2_TRACE_STD,"Setting up %u unique standard(s)",
0351 std_cnt);
0352 if (!std_cnt) return NULL;
0353
0354 stddefs = kcalloc(std_cnt, sizeof(struct v4l2_standard),
0355 GFP_KERNEL);
0356 if (!stddefs)
0357 return NULL;
0358
0359 for (idx = 0; idx < std_cnt; idx++)
0360 stddefs[idx].index = idx;
0361
0362 idx = 0;
0363
0364
0365 for (idx2 = 0; (idx2 < ARRAY_SIZE(std_mixes)) && (idx < std_cnt);
0366 idx2++) {
0367 if (!(id & std_mixes[idx2])) continue;
0368 if (pvr2_std_fill(stddefs+idx,std_mixes[idx2])) idx++;
0369 }
0370
0371 for (idmsk = 1, cmsk = id; cmsk && (idx < std_cnt); idmsk <<= 1) {
0372 if (!(idmsk & cmsk)) continue;
0373 cmsk &= ~idmsk;
0374 if (!pvr2_std_fill(stddefs+idx,idmsk)) continue;
0375 idx++;
0376 }
0377
0378 *countptr = std_cnt;
0379 return stddefs;
0380 }
0381
0382 v4l2_std_id pvr2_std_get_usable(void)
0383 {
0384 return CSTD_ALL;
0385 }