// SPDX-License-Identifier: GPL-2.0-or-later /* * Mars MR97310A library * * The original mr97310a driver, which supported the Aiptek Pencam VGA+, is * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com> * * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+ * and for the routines for detecting and classifying these various cameras, * is Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> * * Support for the control settings for the CIF cameras is * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> and * Thomas Kaiser <thomas@kaiser-linux.li> * * Support for the control settings for the VGA cameras is * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> * * Several previously unsupported cameras are owned and have been tested by * Hans de Goede <hdegoede@redhat.com> and * Thomas Kaiser <thomas@kaiser-linux.li> and * Theodore Kilgore <kilgota@auburn.edu> and * Edmond Rodriguez <erodrig_97@yahoo.com> and * Aurelien Jacobs <aurel@gnuage.org> * * The MR97311A support in gspca/mars.c has been helpful in understanding some * of the registers in these cameras.
*/
/* This function is called at probe time */ staticint sd_config(struct gspca_dev *gspca_dev, conststruct usb_device_id *id)
{ struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; int err_code;
/* Several of the supported CIF cameras share the same USB ID but * require different initializations and different control settings. * The same is true of the VGA cameras. Therefore, we are forced * to start the initialization process in order to determine which * camera is present. Some of the supported cameras require the * memory pointer to be set to 0 as the very first item of business * or else they will not stream. So we do that immediately.
*/
err_code = zero_the_pointer(gspca_dev); if (err_code < 0) return err_code;
err_code = stream_start(gspca_dev); if (err_code < 0) return err_code;
/* Now, the query for sensor type. */
err_code = cam_get_response16(gspca_dev, 0x07, 1); if (err_code < 0) return err_code;
if (id->idProduct == 0x0110 || id->idProduct == 0x010e) {
sd->cam_type = CAM_TYPE_CIF;
cam->nmodes--; /* * All but one of the known CIF cameras share the same USB ID, * but two different init routines are in use, and the control * settings are different, too. We need to detect which camera * of the two known varieties is connected! * * A list of known CIF cameras follows. They all report either * 0200 for type 0 or 0300 for type 1. * If you have another to report, please do * * Name sd->sensor_type reported by * * Sakar 56379 Spy-shot 0 T. Kilgore * Innovage 0 T. Kilgore * Vivitar Mini 0 H. De Goede * Vivitar Mini 0 E. Rodriguez * Vivitar Mini 1 T. Kilgore * Elta-Media 8212dc 1 T. Kaiser * Philips dig. keych. 1 T. Kilgore * Trust Spyc@m 100 1 A. Jacobs
*/ switch (gspca_dev->usb_buf[0]) { case 2:
sd->sensor_type = 0; break; case 3:
sd->sensor_type = 1; break; default:
pr_err("Unknown CIF Sensor id : %02x\n",
gspca_dev->usb_buf[1]); return -ENODEV;
}
gspca_dbg(gspca_dev, D_PROBE, "MR97310A CIF camera detected, sensor: %d\n",
sd->sensor_type);
} else {
sd->cam_type = CAM_TYPE_VGA;
/* * Here is a table of the responses to the query for sensor * type, from the known MR97310A VGA cameras. Six different * cameras of which five share the same USB ID. * * Name gspca_dev->usb_buf[] sd->sensor_type * sd->do_lcd_stop * Aiptek Pencam VGA+ 0300 0 1 * ION digital 0300 0 1 * Argus DC-1620 0450 1 0 * Argus QuickClix 0420 1 1 * Sakar 77379 Digital 0350 0 1 * Sakar 1638x CyberPix 0120 0 2 * * Based upon these results, we assume default settings * and then correct as necessary, as follows. *
*/
sd->sensor_type = 1;
sd->do_lcd_stop = 0;
sd->adj_colors = 0; if (gspca_dev->usb_buf[0] == 0x01) {
sd->sensor_type = 2;
} elseif ((gspca_dev->usb_buf[0] != 0x03) &&
(gspca_dev->usb_buf[0] != 0x04)) {
pr_err("Unknown VGA Sensor id Byte 0: %02x\n",
gspca_dev->usb_buf[0]);
pr_err("Defaults assumed, may not work\n");
pr_err("Please report this\n");
} /* Sakar Digital color needs to be adjusted. */ if ((gspca_dev->usb_buf[0] == 0x03) &&
(gspca_dev->usb_buf[1] == 0x50))
sd->adj_colors = 1; if (gspca_dev->usb_buf[0] == 0x04) {
sd->do_lcd_stop = 1; switch (gspca_dev->usb_buf[1]) { case 0x50:
sd->sensor_type = 0;
gspca_dbg(gspca_dev, D_PROBE, "sensor_type corrected to 0\n"); break; case 0x20: /* Nothing to do here. */ break; default:
pr_err("Unknown VGA Sensor id Byte 1: %02x\n",
gspca_dev->usb_buf[1]);
pr_err("Defaults assumed, may not work\n");
pr_err("Please report this\n");
}
}
gspca_dbg(gspca_dev, D_PROBE, "MR97310A VGA camera detected, sensor: %d\n",
sd->sensor_type);
} /* Stop streaming as we've started it only to probe the sensor type. */
sd_stopN(gspca_dev);
if (force_sensor_type != -1) {
sd->sensor_type = !!force_sensor_type;
gspca_dbg(gspca_dev, D_PROBE, "Forcing sensor type to: %d\n",
sd->sensor_type);
}
return 0;
}
/* this function is called at probe and resume time */ staticint sd_init(struct gspca_dev *gspca_dev)
{ return 0;
}
staticint start_cif_cam(struct gspca_dev *gspca_dev)
{ struct sd *sd = (struct sd *) gspca_dev;
__u8 *data = gspca_dev->usb_buf; int err_code; staticconst __u8 startup_string[] = {
0x00,
0x0d,
0x01,
0x00, /* Hsize/8 for 352 or 320 */
0x00, /* Vsize/4 for 288 or 240 */
0x13, /* or 0xbb, depends on sensor */
0x00, /* Hstart, depends on res. */
0x00, /* reserved ? */
0x00, /* Vstart, depends on res. and sensor */
0x50, /* 0x54 to get 176 or 160 */
0xc0
};
/* Note: Some of the above descriptions guessed from MR97113A driver */
memcpy(data, startup_string, 11); if (sd->sensor_type)
data[5] = 0xbb;
switch (gspca_dev->pixfmt.width) { case 160:
data[9] |= 0x04; /* reg 8, 2:1 scale down from 320 */
fallthrough; case 320: default:
data[3] = 0x28; /* reg 2, H size/8 */
data[4] = 0x3c; /* reg 3, V size/4 */
data[6] = 0x14; /* reg 5, H start */
data[8] = 0x1a + sd->sensor_type; /* reg 7, V start */ break; case 176:
data[9] |= 0x04; /* reg 8, 2:1 scale down from 352 */
fallthrough; case 352:
data[3] = 0x2c; /* reg 2, H size/8 */
data[4] = 0x48; /* reg 3, V size/4 */
data[6] = 0x06; /* reg 5, H start */
data[8] = 0x06 - sd->sensor_type; /* reg 7, V start */ break;
}
err_code = mr_write(gspca_dev, 11); if (err_code < 0) return err_code;
/* Some of the VGA cameras require the memory pointer * to be set to 0 again. We have been forced to start the * stream in sd_config() to detect the hardware, and closed it.
* Thus, we need here to do a completely fresh and clean start. */
err_code = zero_the_pointer(gspca_dev); if (err_code < 0) return err_code;
err_code = stream_start(gspca_dev); if (err_code < 0) return err_code;
stream_stop(gspca_dev); /* Not all the cams need this, but even if not, probably a good idea */
zero_the_pointer(gspca_dev); if (sd->do_lcd_stop)
lcd_stop(gspca_dev);
}
staticvoid setbrightness(struct gspca_dev *gspca_dev, s32 val)
{ struct sd *sd = (struct sd *) gspca_dev;
u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */
u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */ staticconst u8 quick_clix_table[] = /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
{ 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15}; if (sd->cam_type == CAM_TYPE_VGA) {
sign_reg += 4;
value_reg += 4;
}
/* Note register 7 is also seen as 0x8x or 0xCx in some dumps */ if (val > 0) {
sensor_write1(gspca_dev, sign_reg, 0x00);
} else {
sensor_write1(gspca_dev, sign_reg, 0x01);
val = 257 - val;
} /* Use lookup table for funky Argus QuickClix brightness */ if (sd->do_lcd_stop)
val = quick_clix_table[val];
if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { /* This cam does not like exposure settings < 300,
so scale 0 - 4095 to 300 - 4095 */
exposure = (expo * 9267) / 10000 + 300;
sensor_write1(gspca_dev, 3, exposure >> 4);
sensor_write1(gspca_dev, 4, exposure & 0x0f);
} elseif (sd->sensor_type == 2) {
exposure = expo;
exposure >>= 3;
sensor_write1(gspca_dev, 3, exposure >> 8);
sensor_write1(gspca_dev, 4, exposure & 0xff);
} else { /* We have both a clock divider and an exposure register. We first calculate the clock divider, as that determines the maximum exposure and then we calculate the exposure register setting (which goes from 0 - 511).
Note our 0 - 4095 exposure is mapped to 0 - 511
milliseconds exposure time */
u8 clockdiv = (60 * expo + 7999) / 8000;
/* Limit framerate to not exceed usb bandwidth */ if (clockdiv < min_clockdiv && gspca_dev->pixfmt.width >= 320)
clockdiv = min_clockdiv; elseif (clockdiv < 2)
clockdiv = 2;
/* Setup controls depending on camera type */ if (sd->cam_type == CAM_TYPE_CIF) { /* No brightness for sensor_type 0 */ if (sd->sensor_type == 0)
has_exposure = has_gain = has_clockdiv = true; else
has_exposure = has_gain = has_brightness = true;
} else { /* All controls need to be disabled if VGA sensor_type is 0 */ if (sd->sensor_type == 0)
; /* no controls! */ elseif (sd->sensor_type == 2)
has_exposure = has_cs_gain = has_contrast = true; elseif (sd->do_lcd_stop)
has_exposure = has_gain = has_argus_brightness =
has_clockdiv = true; else
has_exposure = has_gain = has_brightness =
has_clockdiv = true;
}
/* Separate brightness control description for Argus QuickClix as it has * different limits from the other mr97310a cameras, and separate gain
* control for Sakar CyberPix camera. */ /* * This control is disabled for CIF type 1 and VGA type 0 cameras. * It does not quite act linearly for the Argus QuickClix camera, * but it does control brightness. The values are 0 - 15 only, and * the table above makes them act consecutively.
*/ if (has_brightness)
v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_BRIGHTNESS, -254, 255, 1,
MR97310A_BRIGHTNESS_DEFAULT); elseif (has_argus_brightness)
v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_BRIGHTNESS, 0, 15, 1,
MR97310A_BRIGHTNESS_DEFAULT); if (has_contrast)
v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_CONTRAST, MR97310A_CONTRAST_MIN,
MR97310A_CONTRAST_MAX, 1, MR97310A_CONTRAST_DEFAULT); if (has_gain)
v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_GAIN, MR97310A_GAIN_MIN, MR97310A_GAIN_MAX,
1, MR97310A_GAIN_DEFAULT); elseif (has_cs_gain)
v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAIN,
MR97310A_CS_GAIN_MIN, MR97310A_CS_GAIN_MAX,
1, MR97310A_CS_GAIN_DEFAULT); if (has_exposure)
sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_EXPOSURE, MR97310A_EXPOSURE_MIN,
MR97310A_EXPOSURE_MAX, 1, MR97310A_EXPOSURE_DEFAULT); if (has_clockdiv)
sd->min_clockdiv = v4l2_ctrl_new_custom(hdl, &clockdiv, NULL);
if (hdl->error) {
pr_err("Could not initialize controls\n"); return hdl->error;
} if (has_exposure && has_clockdiv)
v4l2_ctrl_cluster(2, &sd->exposure); return 0;
}
/* Include pac common sof detection functions */ #include"pac_common.h"
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.