1fd9871f7SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 249b61ec9SHans de Goede /* 349b61ec9SHans de Goede * gspca ViCam subdriver 449b61ec9SHans de Goede * 549b61ec9SHans de Goede * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com> 649b61ec9SHans de Goede * 749b61ec9SHans de Goede * Based on the usbvideo vicam driver, which is: 849b61ec9SHans de Goede * 949b61ec9SHans de Goede * Copyright (c) 2002 Joe Burks (jburks@wavicle.org), 10ccb7cc00SChris Cheney * Chris Cheney (chris.cheney@gmail.com), 1149b61ec9SHans de Goede * Pavel Machek (pavel@ucw.cz), 1249b61ec9SHans de Goede * John Tyner (jtyner@cs.ucr.edu), 1349b61ec9SHans de Goede * Monroe Williams (monroe@pobox.com) 1449b61ec9SHans de Goede */ 1549b61ec9SHans de Goede 16133a9fe9SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 17133a9fe9SJoe Perches 1849b61ec9SHans de Goede #define MODULE_NAME "vicam" 1949b61ec9SHans de Goede #define HEADER_SIZE 64 2049b61ec9SHans de Goede 2149b61ec9SHans de Goede #include <linux/workqueue.h> 2249b61ec9SHans de Goede #include <linux/slab.h> 2349b61ec9SHans de Goede #include <linux/firmware.h> 2449b61ec9SHans de Goede #include <linux/ihex.h> 2549b61ec9SHans de Goede #include "gspca.h" 2649b61ec9SHans de Goede 27d74185b4STim Gardner #define VICAM_FIRMWARE "vicam/firmware.fw" 28d74185b4STim Gardner 2949b61ec9SHans de Goede MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 3049b61ec9SHans de Goede MODULE_DESCRIPTION("GSPCA ViCam USB Camera Driver"); 3149b61ec9SHans de Goede MODULE_LICENSE("GPL"); 32d74185b4STim Gardner MODULE_FIRMWARE(VICAM_FIRMWARE); 3349b61ec9SHans de Goede 3449b61ec9SHans de Goede struct sd { 3549b61ec9SHans de Goede struct gspca_dev gspca_dev; /* !! must be the first item */ 3649b61ec9SHans de Goede struct work_struct work_struct; 3749b61ec9SHans de Goede }; 3849b61ec9SHans de Goede 3949b61ec9SHans de Goede /* The vicam sensor has a resolution of 512 x 244, with I believe square 4049b61ec9SHans de Goede pixels, but this is forced to a 4:3 ratio by optics. So it has 4149b61ec9SHans de Goede non square pixels :( */ 4249b61ec9SHans de Goede static struct v4l2_pix_format vicam_mode[] = { 4349b61ec9SHans de Goede { 256, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, 4449b61ec9SHans de Goede .bytesperline = 256, 4549b61ec9SHans de Goede .sizeimage = 256 * 122, 4649b61ec9SHans de Goede .colorspace = V4L2_COLORSPACE_SRGB,}, 4749b61ec9SHans de Goede /* 2 modes with somewhat more square pixels */ 4849b61ec9SHans de Goede { 256, 200, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, 4949b61ec9SHans de Goede .bytesperline = 256, 5049b61ec9SHans de Goede .sizeimage = 256 * 200, 5149b61ec9SHans de Goede .colorspace = V4L2_COLORSPACE_SRGB,}, 5249b61ec9SHans de Goede { 256, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, 5349b61ec9SHans de Goede .bytesperline = 256, 5449b61ec9SHans de Goede .sizeimage = 256 * 240, 5549b61ec9SHans de Goede .colorspace = V4L2_COLORSPACE_SRGB,}, 5649b61ec9SHans de Goede #if 0 /* This mode has extremely non square pixels, testing use only */ 5749b61ec9SHans de Goede { 512, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, 5849b61ec9SHans de Goede .bytesperline = 512, 5949b61ec9SHans de Goede .sizeimage = 512 * 122, 6049b61ec9SHans de Goede .colorspace = V4L2_COLORSPACE_SRGB,}, 6149b61ec9SHans de Goede #endif 6249b61ec9SHans de Goede { 512, 244, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, 6349b61ec9SHans de Goede .bytesperline = 512, 6449b61ec9SHans de Goede .sizeimage = 512 * 244, 6549b61ec9SHans de Goede .colorspace = V4L2_COLORSPACE_SRGB,}, 6649b61ec9SHans de Goede }; 6749b61ec9SHans de Goede 6849b61ec9SHans de Goede static int vicam_control_msg(struct gspca_dev *gspca_dev, u8 request, 6949b61ec9SHans de Goede u16 value, u16 index, u8 *data, u16 len) 7049b61ec9SHans de Goede { 7149b61ec9SHans de Goede int ret; 7249b61ec9SHans de Goede 7349b61ec9SHans de Goede ret = usb_control_msg(gspca_dev->dev, 7449b61ec9SHans de Goede usb_sndctrlpipe(gspca_dev->dev, 0), 7549b61ec9SHans de Goede request, 7649b61ec9SHans de Goede USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 7749b61ec9SHans de Goede value, index, data, len, 1000); 7849b61ec9SHans de Goede if (ret < 0) 79133a9fe9SJoe Perches pr_err("control msg req %02X error %d\n", request, ret); 8049b61ec9SHans de Goede 8149b61ec9SHans de Goede return ret; 8249b61ec9SHans de Goede } 8349b61ec9SHans de Goede 8449b61ec9SHans de Goede static int vicam_set_camera_power(struct gspca_dev *gspca_dev, int state) 8549b61ec9SHans de Goede { 8649b61ec9SHans de Goede int ret; 8749b61ec9SHans de Goede 8849b61ec9SHans de Goede ret = vicam_control_msg(gspca_dev, 0x50, state, 0, NULL, 0); 8949b61ec9SHans de Goede if (ret < 0) 9049b61ec9SHans de Goede return ret; 9149b61ec9SHans de Goede 9249b61ec9SHans de Goede if (state) 9349b61ec9SHans de Goede ret = vicam_control_msg(gspca_dev, 0x55, 1, 0, NULL, 0); 9449b61ec9SHans de Goede 9549b61ec9SHans de Goede return ret; 9649b61ec9SHans de Goede } 9749b61ec9SHans de Goede 9849b61ec9SHans de Goede /* 99844db450SHans de Goede * request and read a block of data 10049b61ec9SHans de Goede */ 10149b61ec9SHans de Goede static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size) 10249b61ec9SHans de Goede { 10349b61ec9SHans de Goede int ret, unscaled_height, act_len = 0; 10449b61ec9SHans de Goede u8 *req_data = gspca_dev->usb_buf; 1054910adf1SHans Verkuil s32 expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure); 1064910adf1SHans Verkuil s32 gain = v4l2_ctrl_g_ctrl(gspca_dev->gain); 10749b61ec9SHans de Goede 10849b61ec9SHans de Goede memset(req_data, 0, 16); 1094910adf1SHans Verkuil req_data[0] = gain; 1101966bc2aSOndrej Zary if (gspca_dev->pixfmt.width == 256) 11149b61ec9SHans de Goede req_data[1] |= 0x01; /* low nibble x-scale */ 1121966bc2aSOndrej Zary if (gspca_dev->pixfmt.height <= 122) { 11349b61ec9SHans de Goede req_data[1] |= 0x10; /* high nibble y-scale */ 1141966bc2aSOndrej Zary unscaled_height = gspca_dev->pixfmt.height * 2; 11549b61ec9SHans de Goede } else 1161966bc2aSOndrej Zary unscaled_height = gspca_dev->pixfmt.height; 11749b61ec9SHans de Goede req_data[2] = 0x90; /* unknown, does not seem to do anything */ 11849b61ec9SHans de Goede if (unscaled_height <= 200) 11949b61ec9SHans de Goede req_data[3] = 0x06; /* vend? */ 12049b61ec9SHans de Goede else if (unscaled_height <= 242) /* Yes 242 not 240 */ 12149b61ec9SHans de Goede req_data[3] = 0x07; /* vend? */ 12249b61ec9SHans de Goede else /* Up to 244 lines with req_data[3] == 0x08 */ 12349b61ec9SHans de Goede req_data[3] = 0x08; /* vend? */ 12449b61ec9SHans de Goede 1254910adf1SHans Verkuil if (expo < 256) { 12649b61ec9SHans de Goede /* Frame rate maxed out, use partial frame expo time */ 1274910adf1SHans Verkuil req_data[4] = 255 - expo; 12849b61ec9SHans de Goede req_data[5] = 0x00; 12949b61ec9SHans de Goede req_data[6] = 0x00; 13049b61ec9SHans de Goede req_data[7] = 0x01; 13149b61ec9SHans de Goede } else { 13249b61ec9SHans de Goede /* Modify frame rate */ 13349b61ec9SHans de Goede req_data[4] = 0x00; 13449b61ec9SHans de Goede req_data[5] = 0x00; 1354910adf1SHans Verkuil req_data[6] = expo & 0xFF; 1364910adf1SHans Verkuil req_data[7] = expo >> 8; 13749b61ec9SHans de Goede } 13849b61ec9SHans de Goede req_data[8] = ((244 - unscaled_height) / 2) & ~0x01; /* vstart */ 13949b61ec9SHans de Goede /* bytes 9-15 do not seem to affect exposure or image quality */ 14049b61ec9SHans de Goede 14149b61ec9SHans de Goede mutex_lock(&gspca_dev->usb_lock); 14249b61ec9SHans de Goede ret = vicam_control_msg(gspca_dev, 0x51, 0x80, 0, req_data, 16); 14349b61ec9SHans de Goede mutex_unlock(&gspca_dev->usb_lock); 14449b61ec9SHans de Goede if (ret < 0) 14549b61ec9SHans de Goede return ret; 14649b61ec9SHans de Goede 14749b61ec9SHans de Goede ret = usb_bulk_msg(gspca_dev->dev, 14849b61ec9SHans de Goede usb_rcvbulkpipe(gspca_dev->dev, 0x81), 14949b61ec9SHans de Goede data, size, &act_len, 10000); 15049b61ec9SHans de Goede /* successful, it returns 0, otherwise negative */ 15149b61ec9SHans de Goede if (ret < 0 || act_len != size) { 152133a9fe9SJoe Perches pr_err("bulk read fail (%d) len %d/%d\n", 15349b61ec9SHans de Goede ret, act_len, size); 15449b61ec9SHans de Goede return -EIO; 15549b61ec9SHans de Goede } 15649b61ec9SHans de Goede return 0; 15749b61ec9SHans de Goede } 15849b61ec9SHans de Goede 159844db450SHans de Goede /* 160844db450SHans de Goede * This function is called as a workqueue function and runs whenever the camera 16149b61ec9SHans de Goede * is streaming data. Because it is a workqueue function it is allowed to sleep 16249b61ec9SHans de Goede * so we can use synchronous USB calls. To avoid possible collisions with other 163844db450SHans de Goede * threads attempting to use gspca_dev->usb_buf we take the usb_lock when 164844db450SHans de Goede * performing USB operations using it. In practice we don't really need this 165844db450SHans de Goede * as the cameras controls are only written from the workqueue. 16649b61ec9SHans de Goede */ 16749b61ec9SHans de Goede static void vicam_dostream(struct work_struct *work) 16849b61ec9SHans de Goede { 16949b61ec9SHans de Goede struct sd *sd = container_of(work, struct sd, work_struct); 17049b61ec9SHans de Goede struct gspca_dev *gspca_dev = &sd->gspca_dev; 17149b61ec9SHans de Goede int ret, frame_sz; 17249b61ec9SHans de Goede u8 *buffer; 17349b61ec9SHans de Goede 17449b61ec9SHans de Goede frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage + 17549b61ec9SHans de Goede HEADER_SIZE; 1765334b342SHans de Goede buffer = kmalloc(frame_sz, GFP_KERNEL); 17749b61ec9SHans de Goede if (!buffer) { 178133a9fe9SJoe Perches pr_err("Couldn't allocate USB buffer\n"); 17949b61ec9SHans de Goede goto exit; 18049b61ec9SHans de Goede } 18149b61ec9SHans de Goede 182345321dcSHans de Goede while (gspca_dev->present && gspca_dev->streaming) { 1834ad34da0SHans Verkuil #ifdef CONFIG_PM 1844ad34da0SHans Verkuil if (gspca_dev->frozen) 1854ad34da0SHans Verkuil break; 1864ad34da0SHans Verkuil #endif 18749b61ec9SHans de Goede ret = vicam_read_frame(gspca_dev, buffer, frame_sz); 18849b61ec9SHans de Goede if (ret < 0) 18949b61ec9SHans de Goede break; 19049b61ec9SHans de Goede 19149b61ec9SHans de Goede /* Note the frame header contents seem to be completely 19249b61ec9SHans de Goede constant, they do not change with either image, or 19349b61ec9SHans de Goede settings. So we simply discard it. The frames have 19449b61ec9SHans de Goede a very similar 64 byte footer, which we don't even 19549b61ec9SHans de Goede bother reading from the cam */ 19649b61ec9SHans de Goede gspca_frame_add(gspca_dev, FIRST_PACKET, 19749b61ec9SHans de Goede buffer + HEADER_SIZE, 19849b61ec9SHans de Goede frame_sz - HEADER_SIZE); 19949b61ec9SHans de Goede gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 20049b61ec9SHans de Goede } 20149b61ec9SHans de Goede exit: 20249b61ec9SHans de Goede kfree(buffer); 20349b61ec9SHans de Goede } 20449b61ec9SHans de Goede 20549b61ec9SHans de Goede /* This function is called at probe time just before sd_init */ 20649b61ec9SHans de Goede static int sd_config(struct gspca_dev *gspca_dev, 20749b61ec9SHans de Goede const struct usb_device_id *id) 20849b61ec9SHans de Goede { 20949b61ec9SHans de Goede struct cam *cam = &gspca_dev->cam; 21049b61ec9SHans de Goede struct sd *sd = (struct sd *)gspca_dev; 21149b61ec9SHans de Goede 21249b61ec9SHans de Goede /* We don't use the buffer gspca allocates so make it small. */ 21349b61ec9SHans de Goede cam->bulk = 1; 21449b61ec9SHans de Goede cam->bulk_size = 64; 21549b61ec9SHans de Goede cam->cam_mode = vicam_mode; 21649b61ec9SHans de Goede cam->nmodes = ARRAY_SIZE(vicam_mode); 21749b61ec9SHans de Goede 21849b61ec9SHans de Goede INIT_WORK(&sd->work_struct, vicam_dostream); 21949b61ec9SHans de Goede 22049b61ec9SHans de Goede return 0; 22149b61ec9SHans de Goede } 22249b61ec9SHans de Goede 22349b61ec9SHans de Goede /* this function is called at probe and resume time */ 22449b61ec9SHans de Goede static int sd_init(struct gspca_dev *gspca_dev) 22549b61ec9SHans de Goede { 22649b61ec9SHans de Goede int ret; 22749b61ec9SHans de Goede const struct ihex_binrec *rec; 228*3f649ab7SKees Cook const struct firmware *fw; 22949b61ec9SHans de Goede u8 *firmware_buf; 23049b61ec9SHans de Goede 231d74185b4STim Gardner ret = request_ihex_firmware(&fw, VICAM_FIRMWARE, 23249b61ec9SHans de Goede &gspca_dev->dev->dev); 23349b61ec9SHans de Goede if (ret) { 234133a9fe9SJoe Perches pr_err("Failed to load \"vicam/firmware.fw\": %d\n", ret); 23549b61ec9SHans de Goede return ret; 23649b61ec9SHans de Goede } 23749b61ec9SHans de Goede 23849b61ec9SHans de Goede firmware_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 23949b61ec9SHans de Goede if (!firmware_buf) { 24049b61ec9SHans de Goede ret = -ENOMEM; 24149b61ec9SHans de Goede goto exit; 24249b61ec9SHans de Goede } 24349b61ec9SHans de Goede for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) { 24449b61ec9SHans de Goede memcpy(firmware_buf, rec->data, be16_to_cpu(rec->len)); 24549b61ec9SHans de Goede ret = vicam_control_msg(gspca_dev, 0xff, 0, 0, firmware_buf, 24649b61ec9SHans de Goede be16_to_cpu(rec->len)); 24749b61ec9SHans de Goede if (ret < 0) 24849b61ec9SHans de Goede break; 24949b61ec9SHans de Goede } 25049b61ec9SHans de Goede 25149b61ec9SHans de Goede kfree(firmware_buf); 25249b61ec9SHans de Goede exit: 25349b61ec9SHans de Goede release_firmware(fw); 25449b61ec9SHans de Goede return ret; 25549b61ec9SHans de Goede } 25649b61ec9SHans de Goede 25749b61ec9SHans de Goede /* Set up for getting frames. */ 25849b61ec9SHans de Goede static int sd_start(struct gspca_dev *gspca_dev) 25949b61ec9SHans de Goede { 26049b61ec9SHans de Goede struct sd *sd = (struct sd *)gspca_dev; 26149b61ec9SHans de Goede int ret; 26249b61ec9SHans de Goede 26349b61ec9SHans de Goede ret = vicam_set_camera_power(gspca_dev, 1); 26449b61ec9SHans de Goede if (ret < 0) 26549b61ec9SHans de Goede return ret; 26649b61ec9SHans de Goede 26795705083SBhaktipriya Shridhar schedule_work(&sd->work_struct); 26849b61ec9SHans de Goede 26949b61ec9SHans de Goede return 0; 27049b61ec9SHans de Goede } 27149b61ec9SHans de Goede 27249b61ec9SHans de Goede /* called on streamoff with alt==0 and on disconnect */ 27349b61ec9SHans de Goede /* the usb_lock is held at entry - restore on exit */ 27449b61ec9SHans de Goede static void sd_stop0(struct gspca_dev *gspca_dev) 27549b61ec9SHans de Goede { 27649b61ec9SHans de Goede struct sd *dev = (struct sd *)gspca_dev; 27749b61ec9SHans de Goede 27849b61ec9SHans de Goede /* wait for the work queue to terminate */ 27949b61ec9SHans de Goede mutex_unlock(&gspca_dev->usb_lock); 28049b61ec9SHans de Goede /* This waits for vicam_dostream to finish */ 28195705083SBhaktipriya Shridhar flush_work(&dev->work_struct); 28249b61ec9SHans de Goede mutex_lock(&gspca_dev->usb_lock); 28349b61ec9SHans de Goede 284345321dcSHans de Goede if (gspca_dev->present) 28549b61ec9SHans de Goede vicam_set_camera_power(gspca_dev, 0); 28649b61ec9SHans de Goede } 28749b61ec9SHans de Goede 2884910adf1SHans Verkuil static int sd_init_controls(struct gspca_dev *gspca_dev) 2894910adf1SHans Verkuil { 2904910adf1SHans Verkuil struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 2914910adf1SHans Verkuil 2924910adf1SHans Verkuil gspca_dev->vdev.ctrl_handler = hdl; 2934910adf1SHans Verkuil v4l2_ctrl_handler_init(hdl, 2); 2944910adf1SHans Verkuil gspca_dev->exposure = v4l2_ctrl_new_std(hdl, NULL, 2954910adf1SHans Verkuil V4L2_CID_EXPOSURE, 0, 2047, 1, 256); 2964910adf1SHans Verkuil gspca_dev->gain = v4l2_ctrl_new_std(hdl, NULL, 2974910adf1SHans Verkuil V4L2_CID_GAIN, 0, 255, 1, 200); 2984910adf1SHans Verkuil 2994910adf1SHans Verkuil if (hdl->error) { 3004910adf1SHans Verkuil pr_err("Could not initialize controls\n"); 3014910adf1SHans Verkuil return hdl->error; 3024910adf1SHans Verkuil } 3034910adf1SHans Verkuil return 0; 3044910adf1SHans Verkuil } 3054910adf1SHans Verkuil 30649b61ec9SHans de Goede /* Table of supported USB devices */ 30749b61ec9SHans de Goede static const struct usb_device_id device_table[] = { 30849b61ec9SHans de Goede {USB_DEVICE(0x04c1, 0x009d)}, 30949b61ec9SHans de Goede {USB_DEVICE(0x0602, 0x1001)}, 31049b61ec9SHans de Goede {} 31149b61ec9SHans de Goede }; 31249b61ec9SHans de Goede 31349b61ec9SHans de Goede MODULE_DEVICE_TABLE(usb, device_table); 31449b61ec9SHans de Goede 31549b61ec9SHans de Goede /* sub-driver description */ 31649b61ec9SHans de Goede static const struct sd_desc sd_desc = { 31749b61ec9SHans de Goede .name = MODULE_NAME, 31849b61ec9SHans de Goede .config = sd_config, 31949b61ec9SHans de Goede .init = sd_init, 3204910adf1SHans Verkuil .init_controls = sd_init_controls, 32149b61ec9SHans de Goede .start = sd_start, 32249b61ec9SHans de Goede .stop0 = sd_stop0, 32349b61ec9SHans de Goede }; 32449b61ec9SHans de Goede 32549b61ec9SHans de Goede /* -- device connect -- */ 32649b61ec9SHans de Goede static int sd_probe(struct usb_interface *intf, 32749b61ec9SHans de Goede const struct usb_device_id *id) 32849b61ec9SHans de Goede { 32949b61ec9SHans de Goede return gspca_dev_probe(intf, id, 33049b61ec9SHans de Goede &sd_desc, 33149b61ec9SHans de Goede sizeof(struct sd), 33249b61ec9SHans de Goede THIS_MODULE); 33349b61ec9SHans de Goede } 33449b61ec9SHans de Goede 33549b61ec9SHans de Goede static struct usb_driver sd_driver = { 33649b61ec9SHans de Goede .name = MODULE_NAME, 33749b61ec9SHans de Goede .id_table = device_table, 33849b61ec9SHans de Goede .probe = sd_probe, 33949b61ec9SHans de Goede .disconnect = gspca_disconnect, 34049b61ec9SHans de Goede #ifdef CONFIG_PM 34149b61ec9SHans de Goede .suspend = gspca_suspend, 34249b61ec9SHans de Goede .resume = gspca_resume, 3438bb58964SHans de Goede .reset_resume = gspca_resume, 34449b61ec9SHans de Goede #endif 34549b61ec9SHans de Goede }; 34649b61ec9SHans de Goede 347ecb3b2b3SGreg Kroah-Hartman module_usb_driver(sd_driver); 348