/drivers/media/video/noon010pc30.c
C | 792 lines | 627 code | 123 blank | 42 comment | 75 complexity | fc0ff08d76260b04b35e5241d1888e3a MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- * Driver for SiliconFile NOON010PC30 CIF (1/11") Image Sensor with ISP
- *
- * Copyright (C) 2010 Samsung Electronics
- * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com>
- *
- * Initial register configuration based on a driver authored by
- * HeungJun Kim <riverful.kim@samsung.com>.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later vergsion.
- */
- #include <linux/delay.h>
- #include <linux/gpio.h>
- #include <linux/i2c.h>
- #include <linux/slab.h>
- #include <linux/regulator/consumer.h>
- #include <media/noon010pc30.h>
- #include <media/v4l2-chip-ident.h>
- #include <linux/videodev2.h>
- #include <media/v4l2-ctrls.h>
- #include <media/v4l2-device.h>
- #include <media/v4l2-mediabus.h>
- #include <media/v4l2-subdev.h>
- static int debug;
- module_param(debug, int, 0644);
- MODULE_PARM_DESC(debug, "Enable module debug trace. Set to 1 to enable.");
- #define MODULE_NAME "NOON010PC30"
- /*
- * Register offsets within a page
- * b15..b8 - page id, b7..b0 - register address
- */
- #define POWER_CTRL_REG 0x0001
- #define PAGEMODE_REG 0x03
- #define DEVICE_ID_REG 0x0004
- #define NOON010PC30_ID 0x86
- #define VDO_CTL_REG(n) (0x0010 + (n))
- #define SYNC_CTL_REG 0x0012
- /* Window size and position */
- #define WIN_ROWH_REG 0x0013
- #define WIN_ROWL_REG 0x0014
- #define WIN_COLH_REG 0x0015
- #define WIN_COLL_REG 0x0016
- #define WIN_HEIGHTH_REG 0x0017
- #define WIN_HEIGHTL_REG 0x0018
- #define WIN_WIDTHH_REG 0x0019
- #define WIN_WIDTHL_REG 0x001A
- #define HBLANKH_REG 0x001B
- #define HBLANKL_REG 0x001C
- #define VSYNCH_REG 0x001D
- #define VSYNCL_REG 0x001E
- /* VSYNC control */
- #define VS_CTL_REG(n) (0x00A1 + (n))
- /* page 1 */
- #define ISP_CTL_REG(n) (0x0110 + (n))
- #define YOFS_REG 0x0119
- #define DARK_YOFS_REG 0x011A
- #define SAT_CTL_REG 0x0120
- #define BSAT_REG 0x0121
- #define RSAT_REG 0x0122
- /* Color correction */
- #define CMC_CTL_REG 0x0130
- #define CMC_OFSGH_REG 0x0133
- #define CMC_OFSGL_REG 0x0135
- #define CMC_SIGN_REG 0x0136
- #define CMC_GOFS_REG 0x0137
- #define CMC_COEF_REG(n) (0x0138 + (n))
- #define CMC_OFS_REG(n) (0x0141 + (n))
- /* Gamma correction */
- #define GMA_CTL_REG 0x0160
- #define GMA_COEF_REG(n) (0x0161 + (n))
- /* Lens Shading */
- #define LENS_CTRL_REG 0x01D0
- #define LENS_XCEN_REG 0x01D1
- #define LENS_YCEN_REG 0x01D2
- #define LENS_RC_REG 0x01D3
- #define LENS_GC_REG 0x01D4
- #define LENS_BC_REG 0x01D5
- #define L_AGON_REG 0x01D6
- #define L_AGOFF_REG 0x01D7
- /* Page 3 - Auto Exposure */
- #define AE_CTL_REG(n) (0x0310 + (n))
- #define AE_CTL9_REG 0x032C
- #define AE_CTL10_REG 0x032D
- #define AE_YLVL_REG 0x031C
- #define AE_YTH_REG(n) (0x031D + (n))
- #define AE_WGT_REG 0x0326
- #define EXP_TIMEH_REG 0x0333
- #define EXP_TIMEM_REG 0x0334
- #define EXP_TIMEL_REG 0x0335
- #define EXP_MMINH_REG 0x0336
- #define EXP_MMINL_REG 0x0337
- #define EXP_MMAXH_REG 0x0338
- #define EXP_MMAXM_REG 0x0339
- #define EXP_MMAXL_REG 0x033A
- /* Page 4 - Auto White Balance */
- #define AWB_CTL_REG(n) (0x0410 + (n))
- #define AWB_ENABE 0x80
- #define AWB_WGHT_REG 0x0419
- #define BGAIN_PAR_REG(n) (0x044F + (n))
- /* Manual white balance, when AWB_CTL2[0]=1 */
- #define MWB_RGAIN_REG 0x0466
- #define MWB_BGAIN_REG 0x0467
- /* The token to mark an array end */
- #define REG_TERM 0xFFFF
- struct noon010_format {
- enum v4l2_mbus_pixelcode code;
- enum v4l2_colorspace colorspace;
- u16 ispctl1_reg;
- };
- struct noon010_frmsize {
- u16 width;
- u16 height;
- int vid_ctl1;
- };
- static const char * const noon010_supply_name[] = {
- "vdd_core", "vddio", "vdda"
- };
- #define NOON010_NUM_SUPPLIES ARRAY_SIZE(noon010_supply_name)
- struct noon010_info {
- struct v4l2_subdev sd;
- struct v4l2_ctrl_handler hdl;
- const struct noon010pc30_platform_data *pdata;
- const struct noon010_format *curr_fmt;
- const struct noon010_frmsize *curr_win;
- unsigned int hflip:1;
- unsigned int vflip:1;
- unsigned int power:1;
- u8 i2c_reg_page;
- struct regulator_bulk_data supply[NOON010_NUM_SUPPLIES];
- u32 gpio_nreset;
- u32 gpio_nstby;
- };
- struct i2c_regval {
- u16 addr;
- u16 val;
- };
- /* Supported resolutions. */
- static const struct noon010_frmsize noon010_sizes[] = {
- {
- .width = 352,
- .height = 288,
- .vid_ctl1 = 0,
- }, {
- .width = 176,
- .height = 144,
- .vid_ctl1 = 0x10,
- }, {
- .width = 88,
- .height = 72,
- .vid_ctl1 = 0x20,
- },
- };
- /* Supported pixel formats. */
- static const struct noon010_format noon010_formats[] = {
- {
- .code = V4L2_MBUS_FMT_YUYV8_2X8,
- .colorspace = V4L2_COLORSPACE_JPEG,
- .ispctl1_reg = 0x03,
- }, {
- .code = V4L2_MBUS_FMT_YVYU8_2X8,
- .colorspace = V4L2_COLORSPACE_JPEG,
- .ispctl1_reg = 0x02,
- }, {
- .code = V4L2_MBUS_FMT_VYUY8_2X8,
- .colorspace = V4L2_COLORSPACE_JPEG,
- .ispctl1_reg = 0,
- }, {
- .code = V4L2_MBUS_FMT_UYVY8_2X8,
- .colorspace = V4L2_COLORSPACE_JPEG,
- .ispctl1_reg = 0x01,
- }, {
- .code = V4L2_MBUS_FMT_RGB565_2X8_BE,
- .colorspace = V4L2_COLORSPACE_JPEG,
- .ispctl1_reg = 0x40,
- },
- };
- static const struct i2c_regval noon010_base_regs[] = {
- { WIN_COLL_REG, 0x06 }, { HBLANKL_REG, 0x7C },
- /* Color corection and saturation */
- { ISP_CTL_REG(0), 0x30 }, { ISP_CTL_REG(2), 0x30 },
- { YOFS_REG, 0x80 }, { DARK_YOFS_REG, 0x04 },
- { SAT_CTL_REG, 0x1F }, { BSAT_REG, 0x90 },
- { CMC_CTL_REG, 0x0F }, { CMC_OFSGH_REG, 0x3C },
- { CMC_OFSGL_REG, 0x2C }, { CMC_SIGN_REG, 0x3F },
- { CMC_COEF_REG(0), 0x79 }, { CMC_OFS_REG(0), 0x00 },
- { CMC_COEF_REG(1), 0x39 }, { CMC_OFS_REG(1), 0x00 },
- { CMC_COEF_REG(2), 0x00 }, { CMC_OFS_REG(2), 0x00 },
- { CMC_COEF_REG(3), 0x11 }, { CMC_OFS_REG(3), 0x8B },
- { CMC_COEF_REG(4), 0x65 }, { CMC_OFS_REG(4), 0x07 },
- { CMC_COEF_REG(5), 0x14 }, { CMC_OFS_REG(5), 0x04 },
- { CMC_COEF_REG(6), 0x01 }, { CMC_OFS_REG(6), 0x9C },
- { CMC_COEF_REG(7), 0x33 }, { CMC_OFS_REG(7), 0x89 },
- { CMC_COEF_REG(8), 0x74 }, { CMC_OFS_REG(8), 0x25 },
- /* Automatic white balance */
- { AWB_CTL_REG(0), 0x78 }, { AWB_CTL_REG(1), 0x2E },
- { AWB_CTL_REG(2), 0x20 }, { AWB_CTL_REG(3), 0x85 },
- /* Auto exposure */
- { AE_CTL_REG(0), 0xDC }, { AE_CTL_REG(1), 0x81 },
- { AE_CTL_REG(2), 0x30 }, { AE_CTL_REG(3), 0xA5 },
- { AE_CTL_REG(4), 0x40 }, { AE_CTL_REG(5), 0x51 },
- { AE_CTL_REG(6), 0x33 }, { AE_CTL_REG(7), 0x7E },
- { AE_CTL9_REG, 0x00 }, { AE_CTL10_REG, 0x02 },
- { AE_YLVL_REG, 0x44 }, { AE_YTH_REG(0), 0x34 },
- { AE_YTH_REG(1), 0x30 }, { AE_WGT_REG, 0xD5 },
- /* Lens shading compensation */
- { LENS_CTRL_REG, 0x01 }, { LENS_XCEN_REG, 0x80 },
- { LENS_YCEN_REG, 0x70 }, { LENS_RC_REG, 0x53 },
- { LENS_GC_REG, 0x40 }, { LENS_BC_REG, 0x3E },
- { REG_TERM, 0 },
- };
- static inline struct noon010_info *to_noon010(struct v4l2_subdev *sd)
- {
- return container_of(sd, struct noon010_info, sd);
- }
- static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
- {
- return &container_of(ctrl->handler, struct noon010_info, hdl)->sd;
- }
- static inline int set_i2c_page(struct noon010_info *info,
- struct i2c_client *client, unsigned int reg)
- {
- u32 page = reg >> 8 & 0xFF;
- int ret = 0;
- if (info->i2c_reg_page != page && (reg & 0xFF) != 0x03) {
- ret = i2c_smbus_write_byte_data(client, PAGEMODE_REG, page);
- if (!ret)
-