Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *      Mars-Semi MR97311A library
0004  *      Copyright (C) 2005 <bradlch@hotmail.com>
0005  *
0006  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
0007  */
0008 
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010 
0011 #define MODULE_NAME "mars"
0012 
0013 #include "gspca.h"
0014 #include "jpeg.h"
0015 
0016 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
0017 MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
0018 MODULE_LICENSE("GPL");
0019 
0020 #define QUALITY 50
0021 
0022 /* specific webcam descriptor */
0023 struct sd {
0024     struct gspca_dev gspca_dev; /* !! must be the first item */
0025 
0026     struct v4l2_ctrl *brightness;
0027     struct v4l2_ctrl *saturation;
0028     struct v4l2_ctrl *sharpness;
0029     struct v4l2_ctrl *gamma;
0030     struct { /* illuminator control cluster */
0031         struct v4l2_ctrl *illum_top;
0032         struct v4l2_ctrl *illum_bottom;
0033     };
0034     u8 jpeg_hdr[JPEG_HDR_SZ];
0035 };
0036 
0037 /* V4L2 controls supported by the driver */
0038 static void setbrightness(struct gspca_dev *gspca_dev, s32 val);
0039 static void setcolors(struct gspca_dev *gspca_dev, s32 val);
0040 static void setgamma(struct gspca_dev *gspca_dev, s32 val);
0041 static void setsharpness(struct gspca_dev *gspca_dev, s32 val);
0042 
0043 static const struct v4l2_pix_format vga_mode[] = {
0044     {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0045         .bytesperline = 320,
0046         .sizeimage = 320 * 240 * 3 / 8 + 590,
0047         .colorspace = V4L2_COLORSPACE_JPEG,
0048         .priv = 2},
0049     {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0050         .bytesperline = 640,
0051         .sizeimage = 640 * 480 * 3 / 8 + 590,
0052         .colorspace = V4L2_COLORSPACE_JPEG,
0053         .priv = 1},
0054 };
0055 
0056 static const __u8 mi_data[0x20] = {
0057 /*   01    02   03     04    05    06    07    08 */
0058     0x48, 0x22, 0x01, 0x47, 0x10, 0x00, 0x00, 0x00,
0059 /*   09    0a   0b     0c    0d    0e    0f    10 */
0060     0x00, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01,
0061 /*   11    12   13     14    15    16    17    18 */
0062     0x30, 0x00, 0x04, 0x00, 0x06, 0x01, 0xe2, 0x02,
0063 /*   19    1a   1b     1c    1d    1e    1f    20 */
0064     0x82, 0x00, 0x20, 0x17, 0x80, 0x08, 0x0c, 0x00
0065 };
0066 
0067 /* write <len> bytes from gspca_dev->usb_buf */
0068 static void reg_w(struct gspca_dev *gspca_dev,
0069          int len)
0070 {
0071     int alen, ret;
0072 
0073     if (gspca_dev->usb_err < 0)
0074         return;
0075 
0076     ret = usb_bulk_msg(gspca_dev->dev,
0077             usb_sndbulkpipe(gspca_dev->dev, 4),
0078             gspca_dev->usb_buf,
0079             len,
0080             &alen,
0081             500);   /* timeout in milliseconds */
0082     if (ret < 0) {
0083         pr_err("reg write [%02x] error %d\n",
0084                gspca_dev->usb_buf[0], ret);
0085         gspca_dev->usb_err = ret;
0086     }
0087 }
0088 
0089 static void mi_w(struct gspca_dev *gspca_dev,
0090          u8 addr,
0091          u8 value)
0092 {
0093     gspca_dev->usb_buf[0] = 0x1f;
0094     gspca_dev->usb_buf[1] = 0;          /* control byte */
0095     gspca_dev->usb_buf[2] = addr;
0096     gspca_dev->usb_buf[3] = value;
0097 
0098     reg_w(gspca_dev, 4);
0099 }
0100 
0101 static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
0102 {
0103     gspca_dev->usb_buf[0] = 0x61;
0104     gspca_dev->usb_buf[1] = val;
0105     reg_w(gspca_dev, 2);
0106 }
0107 
0108 static void setcolors(struct gspca_dev *gspca_dev, s32 val)
0109 {
0110     gspca_dev->usb_buf[0] = 0x5f;
0111     gspca_dev->usb_buf[1] = val << 3;
0112     gspca_dev->usb_buf[2] = ((val >> 2) & 0xf8) | 0x04;
0113     reg_w(gspca_dev, 3);
0114 }
0115 
0116 static void setgamma(struct gspca_dev *gspca_dev, s32 val)
0117 {
0118     gspca_dev->usb_buf[0] = 0x06;
0119     gspca_dev->usb_buf[1] = val * 0x40;
0120     reg_w(gspca_dev, 2);
0121 }
0122 
0123 static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
0124 {
0125     gspca_dev->usb_buf[0] = 0x67;
0126     gspca_dev->usb_buf[1] = val * 4 + 3;
0127     reg_w(gspca_dev, 2);
0128 }
0129 
0130 static void setilluminators(struct gspca_dev *gspca_dev, bool top, bool bottom)
0131 {
0132     /* both are off if not streaming */
0133     gspca_dev->usb_buf[0] = 0x22;
0134     if (top)
0135         gspca_dev->usb_buf[1] = 0x76;
0136     else if (bottom)
0137         gspca_dev->usb_buf[1] = 0x7a;
0138     else
0139         gspca_dev->usb_buf[1] = 0x7e;
0140     reg_w(gspca_dev, 2);
0141 }
0142 
0143 static int mars_s_ctrl(struct v4l2_ctrl *ctrl)
0144 {
0145     struct gspca_dev *gspca_dev =
0146         container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0147     struct sd *sd = (struct sd *)gspca_dev;
0148 
0149     gspca_dev->usb_err = 0;
0150 
0151     if (ctrl->id == V4L2_CID_ILLUMINATORS_1) {
0152         /* only one can be on at a time */
0153         if (ctrl->is_new && ctrl->val)
0154             sd->illum_bottom->val = 0;
0155         if (sd->illum_bottom->is_new && sd->illum_bottom->val)
0156             sd->illum_top->val = 0;
0157     }
0158 
0159     if (!gspca_dev->streaming)
0160         return 0;
0161 
0162     switch (ctrl->id) {
0163     case V4L2_CID_BRIGHTNESS:
0164         setbrightness(gspca_dev, ctrl->val);
0165         break;
0166     case V4L2_CID_SATURATION:
0167         setcolors(gspca_dev, ctrl->val);
0168         break;
0169     case V4L2_CID_GAMMA:
0170         setgamma(gspca_dev, ctrl->val);
0171         break;
0172     case V4L2_CID_ILLUMINATORS_1:
0173         setilluminators(gspca_dev, sd->illum_top->val,
0174                        sd->illum_bottom->val);
0175         break;
0176     case V4L2_CID_SHARPNESS:
0177         setsharpness(gspca_dev, ctrl->val);
0178         break;
0179     default:
0180         return -EINVAL;
0181     }
0182     return gspca_dev->usb_err;
0183 }
0184 
0185 static const struct v4l2_ctrl_ops mars_ctrl_ops = {
0186     .s_ctrl = mars_s_ctrl,
0187 };
0188 
0189 /* this function is called at probe time */
0190 static int sd_init_controls(struct gspca_dev *gspca_dev)
0191 {
0192     struct sd *sd = (struct sd *) gspca_dev;
0193     struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
0194 
0195     gspca_dev->vdev.ctrl_handler = hdl;
0196     v4l2_ctrl_handler_init(hdl, 6);
0197     sd->brightness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
0198             V4L2_CID_BRIGHTNESS, 0, 30, 1, 15);
0199     sd->saturation = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
0200             V4L2_CID_SATURATION, 0, 255, 1, 200);
0201     sd->gamma = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
0202             V4L2_CID_GAMMA, 0, 3, 1, 1);
0203     sd->sharpness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
0204             V4L2_CID_SHARPNESS, 0, 2, 1, 1);
0205     sd->illum_top = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
0206             V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
0207     sd->illum_top->flags |= V4L2_CTRL_FLAG_UPDATE;
0208     sd->illum_bottom = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
0209             V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0);
0210     sd->illum_bottom->flags |= V4L2_CTRL_FLAG_UPDATE;
0211     if (hdl->error) {
0212         pr_err("Could not initialize controls\n");
0213         return hdl->error;
0214     }
0215     v4l2_ctrl_cluster(2, &sd->illum_top);
0216     return 0;
0217 }
0218 
0219 /* this function is called at probe time */
0220 static int sd_config(struct gspca_dev *gspca_dev,
0221             const struct usb_device_id *id)
0222 {
0223     struct cam *cam;
0224 
0225     cam = &gspca_dev->cam;
0226     cam->cam_mode = vga_mode;
0227     cam->nmodes = ARRAY_SIZE(vga_mode);
0228     return 0;
0229 }
0230 
0231 /* this function is called at probe and resume time */
0232 static int sd_init(struct gspca_dev *gspca_dev)
0233 {
0234     return 0;
0235 }
0236 
0237 static int sd_start(struct gspca_dev *gspca_dev)
0238 {
0239     struct sd *sd = (struct sd *) gspca_dev;
0240     u8 *data;
0241     int i;
0242 
0243     /* create the JPEG header */
0244     jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
0245             gspca_dev->pixfmt.width,
0246             0x21);      /* JPEG 422 */
0247     jpeg_set_qual(sd->jpeg_hdr, QUALITY);
0248 
0249     data = gspca_dev->usb_buf;
0250 
0251     data[0] = 0x01;     /* address */
0252     data[1] = 0x01;
0253     reg_w(gspca_dev, 2);
0254 
0255     /*
0256        Initialize the MR97113 chip register
0257      */
0258     data[0] = 0x00;     /* address */
0259     data[1] = 0x0c | 0x01;  /* reg 0 */
0260     data[2] = 0x01;     /* reg 1 */
0261     data[3] = gspca_dev->pixfmt.width / 8;  /* h_size , reg 2 */
0262     data[4] = gspca_dev->pixfmt.height / 8; /* v_size , reg 3 */
0263     data[5] = 0x30;     /* reg 4, MI, PAS5101 :
0264                  *  0x30 for 24mhz , 0x28 for 12mhz */
0265     data[6] = 0x02;     /* reg 5, H start - was 0x04 */
0266     data[7] = v4l2_ctrl_g_ctrl(sd->gamma) * 0x40;   /* reg 0x06: gamma */
0267     data[8] = 0x01;     /* reg 7, V start - was 0x03 */
0268 /*  if (h_size == 320 ) */
0269 /*      data[9]= 0x56;   * reg 8, 24MHz, 2:1 scale down */
0270 /*  else */
0271     data[9] = 0x52;     /* reg 8, 24MHz, no scale down */
0272 /*jfm: from win trace*/
0273     data[10] = 0x18;
0274 
0275     reg_w(gspca_dev, 11);
0276 
0277     data[0] = 0x23;     /* address */
0278     data[1] = 0x09;     /* reg 35, append frame header */
0279 
0280     reg_w(gspca_dev, 2);
0281 
0282     data[0] = 0x3c;     /* address */
0283 /*  if (gspca_dev->width == 1280) */
0284 /*      data[1] = 200;   * reg 60, pc-cam frame size
0285                  *  (unit: 4KB) 800KB */
0286 /*  else */
0287     data[1] = 50;       /* 50 reg 60, pc-cam frame size
0288                  *  (unit: 4KB) 200KB */
0289     reg_w(gspca_dev, 2);
0290 
0291     /* auto dark-gain */
0292     data[0] = 0x5e;     /* address */
0293     data[1] = 0;        /* reg 94, Y Gain (auto) */
0294 /*jfm: from win trace*/
0295                 /* reg 0x5f/0x60 (LE) = saturation */
0296                 /* h (60): xxxx x100
0297                  * l (5f): xxxx x000 */
0298     data[2] = v4l2_ctrl_g_ctrl(sd->saturation) << 3;
0299     data[3] = ((v4l2_ctrl_g_ctrl(sd->saturation) >> 2) & 0xf8) | 0x04;
0300     data[4] = v4l2_ctrl_g_ctrl(sd->brightness); /* reg 0x61 = brightness */
0301     data[5] = 0x00;
0302 
0303     reg_w(gspca_dev, 6);
0304 
0305     data[0] = 0x67;
0306 /*jfm: from win trace*/
0307     data[1] = v4l2_ctrl_g_ctrl(sd->sharpness) * 4 + 3;
0308     data[2] = 0x14;
0309     reg_w(gspca_dev, 3);
0310 
0311     data[0] = 0x69;
0312     data[1] = 0x2f;
0313     data[2] = 0x28;
0314     data[3] = 0x42;
0315     reg_w(gspca_dev, 4);
0316 
0317     data[0] = 0x63;
0318     data[1] = 0x07;
0319     reg_w(gspca_dev, 2);
0320 /*jfm: win trace - many writes here to reg 0x64*/
0321 
0322     /* initialize the MI sensor */
0323     for (i = 0; i < sizeof mi_data; i++)
0324         mi_w(gspca_dev, i + 1, mi_data[i]);
0325 
0326     data[0] = 0x00;
0327     data[1] = 0x4d;     /* ISOC transferring enable... */
0328     reg_w(gspca_dev, 2);
0329 
0330     setilluminators(gspca_dev, v4l2_ctrl_g_ctrl(sd->illum_top),
0331                    v4l2_ctrl_g_ctrl(sd->illum_bottom));
0332 
0333     return gspca_dev->usb_err;
0334 }
0335 
0336 static void sd_stopN(struct gspca_dev *gspca_dev)
0337 {
0338     struct sd *sd = (struct sd *) gspca_dev;
0339 
0340     if (v4l2_ctrl_g_ctrl(sd->illum_top) ||
0341         v4l2_ctrl_g_ctrl(sd->illum_bottom)) {
0342         setilluminators(gspca_dev, false, false);
0343         msleep(20);
0344     }
0345 
0346     gspca_dev->usb_buf[0] = 1;
0347     gspca_dev->usb_buf[1] = 0;
0348     reg_w(gspca_dev, 2);
0349 }
0350 
0351 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
0352             u8 *data,           /* isoc packet */
0353             int len)            /* iso packet length */
0354 {
0355     struct sd *sd = (struct sd *) gspca_dev;
0356     int p;
0357 
0358     if (len < 6) {
0359 /*      gspca_dev->last_packet_type = DISCARD_PACKET; */
0360         return;
0361     }
0362     for (p = 0; p < len - 6; p++) {
0363         if (data[0 + p] == 0xff
0364             && data[1 + p] == 0xff
0365             && data[2 + p] == 0x00
0366             && data[3 + p] == 0xff
0367             && data[4 + p] == 0x96) {
0368             if (data[5 + p] == 0x64
0369                 || data[5 + p] == 0x65
0370                 || data[5 + p] == 0x66
0371                 || data[5 + p] == 0x67) {
0372                 gspca_dbg(gspca_dev, D_PACK, "sof offset: %d len: %d\n",
0373                       p, len);
0374                 gspca_frame_add(gspca_dev, LAST_PACKET,
0375                         data, p);
0376 
0377                 /* put the JPEG header */
0378                 gspca_frame_add(gspca_dev, FIRST_PACKET,
0379                     sd->jpeg_hdr, JPEG_HDR_SZ);
0380                 data += p + 16;
0381                 len -= p + 16;
0382                 break;
0383             }
0384         }
0385     }
0386     gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
0387 }
0388 
0389 /* sub-driver description */
0390 static const struct sd_desc sd_desc = {
0391     .name = MODULE_NAME,
0392     .config = sd_config,
0393     .init = sd_init,
0394     .init_controls = sd_init_controls,
0395     .start = sd_start,
0396     .stopN = sd_stopN,
0397     .pkt_scan = sd_pkt_scan,
0398 };
0399 
0400 /* -- module initialisation -- */
0401 static const struct usb_device_id device_table[] = {
0402     {USB_DEVICE(0x093a, 0x050f)},
0403     {}
0404 };
0405 MODULE_DEVICE_TABLE(usb, device_table);
0406 
0407 /* -- device connect -- */
0408 static int sd_probe(struct usb_interface *intf,
0409             const struct usb_device_id *id)
0410 {
0411     return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
0412                 THIS_MODULE);
0413 }
0414 
0415 static struct usb_driver sd_driver = {
0416     .name = MODULE_NAME,
0417     .id_table = device_table,
0418     .probe = sd_probe,
0419     .disconnect = gspca_disconnect,
0420 #ifdef CONFIG_PM
0421     .suspend = gspca_suspend,
0422     .resume = gspca_resume,
0423     .reset_resume = gspca_resume,
0424 #endif
0425 };
0426 
0427 module_usb_driver(sd_driver);