diff options
Diffstat (limited to 'drivers/media/video/gspca/zc3xx.c')
-rw-r--r-- | drivers/media/video/gspca/zc3xx.c | 92 |
1 files changed, 60 insertions, 32 deletions
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index d02aa5c8472a..4473f0fb8b73 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #define MODULE_NAME "zc3xx" | 22 | #define MODULE_NAME "zc3xx" |
23 | 23 | ||
24 | #include <linux/input.h> | 24 | #include <linux/input.h> |
25 | #include <linux/slab.h> | ||
26 | #include "gspca.h" | 25 | #include "gspca.h" |
27 | #include "jpeg.h" | 26 | #include "jpeg.h" |
28 | 27 | ||
@@ -40,15 +39,16 @@ static int force_sensor = -1; | |||
40 | struct sd { | 39 | struct sd { |
41 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 40 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
42 | 41 | ||
42 | u8 brightness; | ||
43 | u8 contrast; | 43 | u8 contrast; |
44 | u8 gamma; | 44 | u8 gamma; |
45 | u8 autogain; | 45 | u8 autogain; |
46 | u8 lightfreq; | 46 | u8 lightfreq; |
47 | u8 sharpness; | 47 | u8 sharpness; |
48 | u8 quality; /* image quality */ | 48 | u8 quality; /* image quality */ |
49 | #define QUALITY_MIN 40 | 49 | #define QUALITY_MIN 50 |
50 | #define QUALITY_MAX 60 | 50 | #define QUALITY_MAX 80 |
51 | #define QUALITY_DEF 50 | 51 | #define QUALITY_DEF 70 |
52 | 52 | ||
53 | u8 sensor; /* Type of image sensor chip */ | 53 | u8 sensor; /* Type of image sensor chip */ |
54 | /* !! values used in different tables */ | 54 | /* !! values used in different tables */ |
@@ -75,10 +75,12 @@ struct sd { | |||
75 | #define SENSOR_MAX 19 | 75 | #define SENSOR_MAX 19 |
76 | unsigned short chip_revision; | 76 | unsigned short chip_revision; |
77 | 77 | ||
78 | u8 *jpeg_hdr; | 78 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
79 | }; | 79 | }; |
80 | 80 | ||
81 | /* V4L2 controls supported by the driver */ | 81 | /* V4L2 controls supported by the driver */ |
82 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
83 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
82 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | 84 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); |
83 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | 85 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); |
84 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 86 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
@@ -93,6 +95,20 @@ static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | |||
93 | static const struct ctrl sd_ctrls[] = { | 95 | static const struct ctrl sd_ctrls[] = { |
94 | { | 96 | { |
95 | { | 97 | { |
98 | .id = V4L2_CID_BRIGHTNESS, | ||
99 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
100 | .name = "Brightness", | ||
101 | .minimum = 0, | ||
102 | .maximum = 255, | ||
103 | .step = 1, | ||
104 | #define BRIGHTNESS_DEF 128 | ||
105 | .default_value = BRIGHTNESS_DEF, | ||
106 | }, | ||
107 | .set = sd_setbrightness, | ||
108 | .get = sd_getbrightness, | ||
109 | }, | ||
110 | { | ||
111 | { | ||
96 | .id = V4L2_CID_CONTRAST, | 112 | .id = V4L2_CID_CONTRAST, |
97 | .type = V4L2_CTRL_TYPE_INTEGER, | 113 | .type = V4L2_CTRL_TYPE_INTEGER, |
98 | .name = "Contrast", | 114 | .name = "Contrast", |
@@ -132,7 +148,7 @@ static const struct ctrl sd_ctrls[] = { | |||
132 | .set = sd_setautogain, | 148 | .set = sd_setautogain, |
133 | .get = sd_getautogain, | 149 | .get = sd_getautogain, |
134 | }, | 150 | }, |
135 | #define LIGHTFREQ_IDX 3 | 151 | #define LIGHTFREQ_IDX 4 |
136 | { | 152 | { |
137 | { | 153 | { |
138 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 154 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -6011,9 +6027,12 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
6011 | struct sd *sd = (struct sd *) gspca_dev; | 6027 | struct sd *sd = (struct sd *) gspca_dev; |
6012 | struct usb_device *dev = gspca_dev->dev; | 6028 | struct usb_device *dev = gspca_dev->dev; |
6013 | const u8 *Tgamma; | 6029 | const u8 *Tgamma; |
6014 | int g, i, k, adj, gp; | 6030 | int g, i, brightness, contrast, adj, gp1, gp2; |
6015 | u8 gr[16]; | 6031 | u8 gr[16]; |
6016 | static const u8 delta_tb[16] = /* delta for contrast */ | 6032 | static const u8 delta_b[16] = /* delta for brightness */ |
6033 | {0x50, 0x38, 0x2d, 0x28, 0x24, 0x21, 0x1e, 0x1d, | ||
6034 | 0x1d, 0x1b, 0x1b, 0x1b, 0x19, 0x18, 0x18, 0x18}; | ||
6035 | static const u8 delta_c[16] = /* delta for contrast */ | ||
6017 | {0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06, | 6036 | {0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06, |
6018 | 0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02}; | 6037 | 0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02}; |
6019 | static const u8 gamma_tb[6][16] = { | 6038 | static const u8 gamma_tb[6][16] = { |
@@ -6033,30 +6052,30 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
6033 | 6052 | ||
6034 | Tgamma = gamma_tb[sd->gamma - 1]; | 6053 | Tgamma = gamma_tb[sd->gamma - 1]; |
6035 | 6054 | ||
6036 | k = ((int) sd->contrast - 128); /* -128 / 128 */ | 6055 | contrast = ((int) sd->contrast - 128); /* -128 / 127 */ |
6056 | brightness = ((int) sd->brightness - 128); /* -128 / 92 */ | ||
6037 | adj = 0; | 6057 | adj = 0; |
6038 | gp = 0; | 6058 | gp1 = gp2 = 0; |
6039 | for (i = 0; i < 16; i++) { | 6059 | for (i = 0; i < 16; i++) { |
6040 | g = Tgamma[i] - delta_tb[i] * k / 256 - adj / 2; | 6060 | g = Tgamma[i] + delta_b[i] * brightness / 256 |
6061 | - delta_c[i] * contrast / 256 - adj / 2; | ||
6041 | if (g > 0xff) | 6062 | if (g > 0xff) |
6042 | g = 0xff; | 6063 | g = 0xff; |
6043 | else if (g < 0) | 6064 | else if (g < 0) |
6044 | g = 0; | 6065 | g = 0; |
6045 | reg_w(dev, g, 0x0120 + i); /* gamma */ | 6066 | reg_w(dev, g, 0x0120 + i); /* gamma */ |
6046 | if (k > 0) | 6067 | if (contrast > 0) |
6047 | adj--; | 6068 | adj--; |
6048 | else | 6069 | else if (contrast < 0) |
6049 | adj++; | 6070 | adj++; |
6050 | 6071 | if (i > 1) | |
6051 | if (i != 0) { | 6072 | gr[i - 1] = (g - gp2) / 2; |
6052 | if (gp == 0) | 6073 | else if (i != 0) |
6053 | gr[i - 1] = 0; | 6074 | gr[0] = gp1 == 0 ? 0 : (g - gp1); |
6054 | else | 6075 | gp2 = gp1; |
6055 | gr[i - 1] = g - gp; | 6076 | gp1 = g; |
6056 | } | ||
6057 | gp = g; | ||
6058 | } | 6077 | } |
6059 | gr[15] = gr[14] / 2; | 6078 | gr[15] = (0xff - gp2) / 2; |
6060 | for (i = 0; i < 16; i++) | 6079 | for (i = 0; i < 16; i++) |
6061 | reg_w(dev, gr[i], 0x0130 + i); /* gradient */ | 6080 | reg_w(dev, gr[i], 0x0130 + i); /* gradient */ |
6062 | } | 6081 | } |
@@ -6744,6 +6763,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6744 | cam->nmodes = ARRAY_SIZE(broken_vga_mode); | 6763 | cam->nmodes = ARRAY_SIZE(broken_vga_mode); |
6745 | break; | 6764 | break; |
6746 | } | 6765 | } |
6766 | sd->brightness = BRIGHTNESS_DEF; | ||
6747 | sd->contrast = CONTRAST_DEF; | 6767 | sd->contrast = CONTRAST_DEF; |
6748 | sd->gamma = gamma[sd->sensor]; | 6768 | sd->gamma = gamma[sd->sensor]; |
6749 | sd->autogain = AUTOGAIN_DEF; | 6769 | sd->autogain = AUTOGAIN_DEF; |
@@ -6798,9 +6818,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6798 | }; | 6818 | }; |
6799 | 6819 | ||
6800 | /* create the JPEG header */ | 6820 | /* create the JPEG header */ |
6801 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | ||
6802 | if (!sd->jpeg_hdr) | ||
6803 | return -ENOMEM; | ||
6804 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 6821 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
6805 | 0x21); /* JPEG 422 */ | 6822 | 0x21); /* JPEG 422 */ |
6806 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 6823 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
@@ -6918,10 +6935,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6918 | reg_w(dev, 0x00, 0x0007); /* (from win traces) */ | 6935 | reg_w(dev, 0x00, 0x0007); /* (from win traces) */ |
6919 | reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); | 6936 | reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); |
6920 | break; | 6937 | break; |
6921 | case SENSOR_PAS202B: | ||
6922 | reg_w(dev, 0x32, 0x0007); /* (from win traces) */ | ||
6923 | reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); | ||
6924 | break; | ||
6925 | } | 6938 | } |
6926 | return 0; | 6939 | return 0; |
6927 | } | 6940 | } |
@@ -6931,7 +6944,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
6931 | { | 6944 | { |
6932 | struct sd *sd = (struct sd *) gspca_dev; | 6945 | struct sd *sd = (struct sd *) gspca_dev; |
6933 | 6946 | ||
6934 | kfree(sd->jpeg_hdr); | ||
6935 | if (!gspca_dev->present) | 6947 | if (!gspca_dev->present) |
6936 | return; | 6948 | return; |
6937 | send_unknown(gspca_dev->dev, sd->sensor); | 6949 | send_unknown(gspca_dev->dev, sd->sensor); |
@@ -6962,6 +6974,24 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
6962 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 6974 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
6963 | } | 6975 | } |
6964 | 6976 | ||
6977 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
6978 | { | ||
6979 | struct sd *sd = (struct sd *) gspca_dev; | ||
6980 | |||
6981 | sd->brightness = val; | ||
6982 | if (gspca_dev->streaming) | ||
6983 | setcontrast(gspca_dev); | ||
6984 | return 0; | ||
6985 | } | ||
6986 | |||
6987 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
6988 | { | ||
6989 | struct sd *sd = (struct sd *) gspca_dev; | ||
6990 | |||
6991 | *val = sd->brightness; | ||
6992 | return 0; | ||
6993 | } | ||
6994 | |||
6965 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | 6995 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) |
6966 | { | 6996 | { |
6967 | struct sd *sd = (struct sd *) gspca_dev; | 6997 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -7163,9 +7193,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
7163 | {USB_DEVICE(0x046d, 0x08aa)}, | 7193 | {USB_DEVICE(0x046d, 0x08aa)}, |
7164 | {USB_DEVICE(0x046d, 0x08ac)}, | 7194 | {USB_DEVICE(0x046d, 0x08ac)}, |
7165 | {USB_DEVICE(0x046d, 0x08ad)}, | 7195 | {USB_DEVICE(0x046d, 0x08ad)}, |
7166 | #if !defined CONFIG_USB_ZC0301 && !defined CONFIG_USB_ZC0301_MODULE | ||
7167 | {USB_DEVICE(0x046d, 0x08ae)}, | 7196 | {USB_DEVICE(0x046d, 0x08ae)}, |
7168 | #endif | ||
7169 | {USB_DEVICE(0x046d, 0x08af)}, | 7197 | {USB_DEVICE(0x046d, 0x08af)}, |
7170 | {USB_DEVICE(0x046d, 0x08b9)}, | 7198 | {USB_DEVICE(0x046d, 0x08b9)}, |
7171 | {USB_DEVICE(0x046d, 0x08d7)}, | 7199 | {USB_DEVICE(0x046d, 0x08d7)}, |