s5c73m3.h 13.9 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
/*
 * Samsung LSI S5C73M3 8M pixel camera driver
 *
 * Copyright (C) 2012, Samsung Electronics, Co., Ltd.
 * Sylwester Nawrocki <s.nawrocki@samsung.com>
 * Andrzej Hajda <a.hajda@samsung.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */
#ifndef S5C73M3_H_
#define S5C73M3_H_

#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/regulator/consumer.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
#include <media/s5c73m3.h>

#define DRIVER_NAME			"S5C73M3"

#define S5C73M3_ISP_FMT			MEDIA_BUS_FMT_VYUY8_2X8
#define S5C73M3_JPEG_FMT		MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8

/* Subdevs pad index definitions */
enum s5c73m3_pads {
	S5C73M3_ISP_PAD,
	S5C73M3_JPEG_PAD,
	S5C73M3_NUM_PADS
};

enum s5c73m3_oif_pads {
	OIF_ISP_PAD,
	OIF_JPEG_PAD,
	OIF_SOURCE_PAD,
	OIF_NUM_PADS
};

#define S5C73M3_SENSOR_FW_LEN		6
#define S5C73M3_SENSOR_TYPE_LEN		12

#define S5C73M3_REG(_addrh, _addrl) (((_addrh) << 16) | _addrl)

#define AHB_MSB_ADDR_PTR			0xfcfc
#define REG_CMDWR_ADDRH				0x0050
#define REG_CMDWR_ADDRL				0x0054
#define REG_CMDRD_ADDRH				0x0058
#define REG_CMDRD_ADDRL				0x005c
#define REG_CMDBUF_ADDR				0x0f14

#define REG_I2C_SEQ_STATUS			S5C73M3_REG(0x0009, 0x59A6)
#define  SEQ_END_PLL				(1<<0x0)
#define  SEQ_END_SENSOR				(1<<0x1)
#define  SEQ_END_GPIO				(1<<0x2)
#define  SEQ_END_FROM				(1<<0x3)
#define  SEQ_END_STABLE_AE_AWB			(1<<0x4)
#define  SEQ_END_READY_I2C_CMD			(1<<0x5)

#define REG_I2C_STATUS				S5C73M3_REG(0x0009, 0x599E)
#define  I2C_STATUS_CIS_I2C			(1<<0x0)
#define  I2C_STATUS_AF_INIT			(1<<0x1)
#define  I2C_STATUS_CAL_DATA			(1<<0x2)
#define  I2C_STATUS_FRAME_COUNT			(1<<0x3)
#define  I2C_STATUS_FROM_INIT			(1<<0x4)
#define  I2C_STATUS_I2C_CIS_STREAM_OFF		(1<<0x5)
#define  I2C_STATUS_I2C_N_CMD_OVER		(1<<0x6)
#define  I2C_STATUS_I2C_N_CMD_MISMATCH		(1<<0x7)
#define  I2C_STATUS_CHECK_BIN_CRC		(1<<0x8)
#define  I2C_STATUS_EXCEPTION			(1<<0x9)
#define  I2C_STATUS_INIF_INIT_STATE		(0x8)

#define REG_STATUS				S5C73M3_REG(0x0009, 0x5080)
#define  REG_STATUS_BOOT_SUB_MAIN_ENTER		0xff01
#define  REG_STATUS_BOOT_SRAM_TIMING_OK		0xff02
#define  REG_STATUS_BOOT_INTERRUPTS_EN		0xff03
#define  REG_STATUS_BOOT_R_PLL_DONE		0xff04
#define  REG_STATUS_BOOT_R_PLL_LOCKTIME_DONE	0xff05
#define  REG_STATUS_BOOT_DELAY_COUNT_DONE	0xff06
#define  REG_STATUS_BOOT_I_PLL_DONE		0xff07
#define  REG_STATUS_BOOT_I_PLL_LOCKTIME_DONE	0xff08
#define  REG_STATUS_BOOT_PLL_INIT_OK		0xff09
#define  REG_STATUS_BOOT_SENSOR_INIT_OK		0xff0a
#define  REG_STATUS_BOOT_GPIO_SETTING_OK	0xff0b
#define  REG_STATUS_BOOT_READ_CAL_DATA_OK	0xff0c
#define  REG_STATUS_BOOT_STABLE_AE_AWB_OK	0xff0d
#define  REG_STATUS_ISP_COMMAND_COMPLETED	0xffff
#define  REG_STATUS_EXCEPTION_OCCURED		0xdead

#define COMM_RESULT_OFFSET			S5C73M3_REG(0x0009, 0x5000)

#define COMM_IMG_OUTPUT				0x0902
#define  COMM_IMG_OUTPUT_HDR			0x0008
#define  COMM_IMG_OUTPUT_YUV			0x0009
#define  COMM_IMG_OUTPUT_INTERLEAVED		0x000d

#define COMM_STILL_PRE_FLASH			0x0a00
#define  COMM_STILL_PRE_FLASH_FIRE		0x0000
#define  COMM_STILL_PRE_FLASH_NON_FIRED		0x0000
#define  COMM_STILL_PRE_FLASH_FIRED		0x0001

#define COMM_STILL_MAIN_FLASH			0x0a02
#define  COMM_STILL_MAIN_FLASH_CANCEL		0x0001
#define  COMM_STILL_MAIN_FLASH_FIRE		0x0002

#define COMM_ZOOM_STEP				0x0b00

#define COMM_IMAGE_EFFECT			0x0b0a
#define  COMM_IMAGE_EFFECT_NONE			0x0001
#define  COMM_IMAGE_EFFECT_NEGATIVE		0x0002
#define  COMM_IMAGE_EFFECT_AQUA			0x0003
#define  COMM_IMAGE_EFFECT_SEPIA		0x0004
#define  COMM_IMAGE_EFFECT_MONO			0x0005

#define COMM_IMAGE_QUALITY			0x0b0c
#define  COMM_IMAGE_QUALITY_SUPERFINE		0x0000
#define  COMM_IMAGE_QUALITY_FINE		0x0001
#define  COMM_IMAGE_QUALITY_NORMAL		0x0002

#define COMM_FLASH_MODE				0x0b0e
#define  COMM_FLASH_MODE_OFF			0x0000
#define  COMM_FLASH_MODE_ON			0x0001
#define  COMM_FLASH_MODE_AUTO			0x0002

#define COMM_FLASH_STATUS			0x0b80
#define  COMM_FLASH_STATUS_OFF			0x0001
#define  COMM_FLASH_STATUS_ON			0x0002
#define  COMM_FLASH_STATUS_AUTO			0x0003

#define COMM_FLASH_TORCH			0x0b12
#define  COMM_FLASH_TORCH_OFF			0x0000
#define  COMM_FLASH_TORCH_ON			0x0001

#define COMM_AE_NEEDS_FLASH			0x0cba
#define  COMM_AE_NEEDS_FLASH_OFF		0x0000
#define  COMM_AE_NEEDS_FLASH_ON			0x0001

#define COMM_CHG_MODE				0x0b10
#define  COMM_CHG_MODE_NEW			0x8000
#define  COMM_CHG_MODE_SUBSAMPLING_HALF		0x2000
#define  COMM_CHG_MODE_SUBSAMPLING_QUARTER	0x4000

#define  COMM_CHG_MODE_YUV_320_240		0x0001
#define  COMM_CHG_MODE_YUV_640_480		0x0002
#define  COMM_CHG_MODE_YUV_880_720		0x0003
#define  COMM_CHG_MODE_YUV_960_720		0x0004
#define  COMM_CHG_MODE_YUV_1184_666		0x0005
#define  COMM_CHG_MODE_YUV_1280_720		0x0006
#define  COMM_CHG_MODE_YUV_1536_864		0x0007
#define  COMM_CHG_MODE_YUV_1600_1200		0x0008
#define  COMM_CHG_MODE_YUV_1632_1224		0x0009
#define  COMM_CHG_MODE_YUV_1920_1080		0x000a
#define  COMM_CHG_MODE_YUV_1920_1440		0x000b
#define  COMM_CHG_MODE_YUV_2304_1296		0x000c
#define  COMM_CHG_MODE_YUV_3264_2448		0x000d
#define  COMM_CHG_MODE_YUV_352_288		0x000e
#define  COMM_CHG_MODE_YUV_1008_672		0x000f

#define  COMM_CHG_MODE_JPEG_640_480		0x0010
#define  COMM_CHG_MODE_JPEG_800_450		0x0020
#define  COMM_CHG_MODE_JPEG_800_600		0x0030
#define  COMM_CHG_MODE_JPEG_1280_720		0x0040
#define  COMM_CHG_MODE_JPEG_1280_960		0x0050
#define  COMM_CHG_MODE_JPEG_1600_900		0x0060
#define  COMM_CHG_MODE_JPEG_1600_1200		0x0070
#define  COMM_CHG_MODE_JPEG_2048_1152		0x0080
#define  COMM_CHG_MODE_JPEG_2048_1536		0x0090
#define  COMM_CHG_MODE_JPEG_2560_1440		0x00a0
#define  COMM_CHG_MODE_JPEG_2560_1920		0x00b0
#define  COMM_CHG_MODE_JPEG_3264_2176		0x00c0
#define  COMM_CHG_MODE_JPEG_1024_768		0x00d0
#define  COMM_CHG_MODE_JPEG_3264_1836		0x00e0
#define  COMM_CHG_MODE_JPEG_3264_2448		0x00f0

#define COMM_AF_CON				0x0e00
#define  COMM_AF_CON_STOP			0x0000
#define  COMM_AF_CON_SCAN			0x0001 /* Full Search */
#define  COMM_AF_CON_START			0x0002 /* Fast Search */

#define COMM_AF_CAL				0x0e06
#define COMM_AF_TOUCH_AF			0x0e0a

#define REG_AF_STATUS				S5C73M3_REG(0x0009, 0x5e80)
#define  REG_CAF_STATUS_FIND_SEARCH_DIR		0x0001
#define  REG_CAF_STATUS_FOCUSING		0x0002
#define  REG_CAF_STATUS_FOCUSED			0x0003
#define  REG_CAF_STATUS_UNFOCUSED		0x0004
#define  REG_AF_STATUS_INVALID			0x0010
#define  REG_AF_STATUS_FOCUSING			0x0020
#define  REG_AF_STATUS_FOCUSED			0x0030
#define  REG_AF_STATUS_UNFOCUSED		0x0040

#define REG_AF_TOUCH_POSITION			S5C73M3_REG(0x0009, 0x5e8e)
#define COMM_AF_FACE_ZOOM			0x0e10

#define COMM_AF_MODE				0x0e02
#define  COMM_AF_MODE_NORMAL			0x0000
#define  COMM_AF_MODE_MACRO			0x0001
#define  COMM_AF_MODE_MOVIE_CAF_START		0x0002
#define  COMM_AF_MODE_MOVIE_CAF_STOP		0x0003
#define  COMM_AF_MODE_PREVIEW_CAF_START		0x0004
#define  COMM_AF_MODE_PREVIEW_CAF_STOP		0x0005

#define COMM_AF_SOFTLANDING			0x0e16
#define  COMM_AF_SOFTLANDING_ON			0x0000
#define  COMM_AF_SOFTLANDING_RES_COMPLETE	0x0001

#define COMM_FACE_DET				0x0e0c
#define  COMM_FACE_DET_OFF			0x0000
#define  COMM_FACE_DET_ON			0x0001

#define COMM_FACE_DET_OSD			0x0e0e
#define  COMM_FACE_DET_OSD_OFF			0x0000
#define  COMM_FACE_DET_OSD_ON			0x0001

#define COMM_AE_CON				0x0c00
#define  COMM_AE_STOP				0x0000 /* lock */
#define  COMM_AE_START				0x0001 /* unlock */

#define COMM_ISO				0x0c02
#define  COMM_ISO_AUTO				0x0000
#define  COMM_ISO_100				0x0001
#define  COMM_ISO_200				0x0002
#define  COMM_ISO_400				0x0003
#define  COMM_ISO_800				0x0004
#define  COMM_ISO_SPORTS			0x0005
#define  COMM_ISO_NIGHT				0x0006
#define  COMM_ISO_INDOOR			0x0007

/* 0x00000 (-2.0 EV)...0x0008 (2.0 EV), 0.5EV step */
#define COMM_EV					0x0c04

#define COMM_METERING				0x0c06
#define  COMM_METERING_CENTER			0x0000
#define  COMM_METERING_SPOT			0x0001
#define  COMM_METERING_AVERAGE			0x0002
#define  COMM_METERING_SMART			0x0003

#define COMM_WDR				0x0c08
#define  COMM_WDR_OFF				0x0000
#define  COMM_WDR_ON				0x0001

#define COMM_FLICKER_MODE			0x0c12
#define  COMM_FLICKER_NONE			0x0000
#define  COMM_FLICKER_MANUAL_50HZ		0x0001
#define  COMM_FLICKER_MANUAL_60HZ		0x0002
#define  COMM_FLICKER_AUTO			0x0003
#define  COMM_FLICKER_AUTO_50HZ			0x0004
#define  COMM_FLICKER_AUTO_60HZ			0x0005

#define COMM_FRAME_RATE				0x0c1e
#define  COMM_FRAME_RATE_AUTO_SET		0x0000
#define  COMM_FRAME_RATE_FIXED_30FPS		0x0002
#define  COMM_FRAME_RATE_FIXED_20FPS		0x0003
#define  COMM_FRAME_RATE_FIXED_15FPS		0x0004
#define  COMM_FRAME_RATE_FIXED_60FPS		0x0007
#define  COMM_FRAME_RATE_FIXED_120FPS		0x0008
#define  COMM_FRAME_RATE_FIXED_7FPS		0x0009
#define  COMM_FRAME_RATE_FIXED_10FPS		0x000a
#define  COMM_FRAME_RATE_FIXED_90FPS		0x000b
#define  COMM_FRAME_RATE_ANTI_SHAKE		0x0013

/* 0x0000...0x0004 -> sharpness: 0, 1, 2, -1, -2 */
#define COMM_SHARPNESS				0x0c14

/* 0x0000...0x0004 -> saturation: 0, 1, 2, -1, -2 */
#define COMM_SATURATION				0x0c16

/* 0x0000...0x0004 -> contrast: 0, 1, 2, -1, -2 */
#define COMM_CONTRAST				0x0c18

#define COMM_SCENE_MODE				0x0c1a
#define  COMM_SCENE_MODE_NONE			0x0000
#define  COMM_SCENE_MODE_PORTRAIT		0x0001
#define  COMM_SCENE_MODE_LANDSCAPE		0x0002
#define  COMM_SCENE_MODE_SPORTS			0x0003
#define  COMM_SCENE_MODE_INDOOR			0x0004
#define  COMM_SCENE_MODE_BEACH			0x0005
#define  COMM_SCENE_MODE_SUNSET			0x0006
#define  COMM_SCENE_MODE_DAWN			0x0007
#define  COMM_SCENE_MODE_FALL			0x0008
#define  COMM_SCENE_MODE_NIGHT			0x0009
#define  COMM_SCENE_MODE_AGAINST_LIGHT		0x000a
#define  COMM_SCENE_MODE_FIRE			0x000b
#define  COMM_SCENE_MODE_TEXT			0x000c
#define  COMM_SCENE_MODE_CANDLE			0x000d

#define COMM_AE_AUTO_BRACKET			0x0b14
#define  COMM_AE_AUTO_BRAKET_EV05		0x0080
#define  COMM_AE_AUTO_BRAKET_EV10		0x0100
#define  COMM_AE_AUTO_BRAKET_EV15		0x0180
#define  COMM_AE_AUTO_BRAKET_EV20		0x0200

#define COMM_SENSOR_STREAMING			0x090a
#define  COMM_SENSOR_STREAMING_OFF		0x0000
#define  COMM_SENSOR_STREAMING_ON		0x0001

#define COMM_AWB_MODE				0x0d02
#define  COMM_AWB_MODE_INCANDESCENT		0x0000
#define  COMM_AWB_MODE_FLUORESCENT1		0x0001
#define  COMM_AWB_MODE_FLUORESCENT2		0x0002
#define  COMM_AWB_MODE_DAYLIGHT			0x0003
#define  COMM_AWB_MODE_CLOUDY			0x0004
#define  COMM_AWB_MODE_AUTO			0x0005

#define COMM_AWB_CON				0x0d00
#define  COMM_AWB_STOP				0x0000 /* lock */
#define  COMM_AWB_START				0x0001 /* unlock */

#define COMM_FW_UPDATE				0x0906
#define  COMM_FW_UPDATE_NOT_READY		0x0000
#define  COMM_FW_UPDATE_SUCCESS			0x0005
#define  COMM_FW_UPDATE_FAIL			0x0007
#define  COMM_FW_UPDATE_BUSY			0xffff


#define S5C73M3_MAX_SUPPLIES			6
#define S5C73M3_DEFAULT_MCLK_FREQ		24000000U

struct s5c73m3_ctrls {
	struct v4l2_ctrl_handler handler;
	struct {
		/* exposure/exposure bias cluster */
		struct v4l2_ctrl *auto_exposure;
		struct v4l2_ctrl *exposure_bias;
		struct v4l2_ctrl *exposure_metering;
	};
	struct {
		/* iso/auto iso cluster */
		struct v4l2_ctrl *auto_iso;
		struct v4l2_ctrl *iso;
	};
	struct v4l2_ctrl *auto_wb;
	struct {
		/* continuous auto focus/auto focus cluster */
		struct v4l2_ctrl *focus_auto;
		struct v4l2_ctrl *af_start;
		struct v4l2_ctrl *af_stop;
		struct v4l2_ctrl *af_status;
		struct v4l2_ctrl *af_distance;
	};

	struct v4l2_ctrl *aaa_lock;
	struct v4l2_ctrl *colorfx;
	struct v4l2_ctrl *contrast;
	struct v4l2_ctrl *saturation;
	struct v4l2_ctrl *sharpness;
	struct v4l2_ctrl *zoom;
	struct v4l2_ctrl *wdr;
	struct v4l2_ctrl *stabilization;
	struct v4l2_ctrl *jpeg_quality;
	struct v4l2_ctrl *scene_mode;
};

enum s5c73m3_gpio_id {
	STBY,
	RST,
	GPIO_NUM,
};

enum s5c73m3_resolution_types {
	RES_ISP,
	RES_JPEG,
};

struct s5c73m3_interval {
	u16 fps_reg;
	struct v4l2_fract interval;
	/* Maximum rectangle for the interval */
	struct v4l2_frmsize_discrete size;
};

struct s5c73m3 {
	struct v4l2_subdev sensor_sd;
	struct media_pad sensor_pads[S5C73M3_NUM_PADS];

	struct v4l2_subdev oif_sd;
	struct media_pad oif_pads[OIF_NUM_PADS];

	struct spi_driver spidrv;
	struct spi_device *spi_dev;
	struct i2c_client *i2c_client;
	u32 i2c_write_address;
	u32 i2c_read_address;

	struct regulator_bulk_data supplies[S5C73M3_MAX_SUPPLIES];
	struct s5c73m3_gpio gpio[GPIO_NUM];

	struct clk *clock;

	/* External master clock frequency */
	u32 mclk_frequency;
	/* Video bus type - MIPI-CSI2/parallel */
	enum v4l2_mbus_type bus_type;

	const struct s5c73m3_frame_size *sensor_pix_size[2];
	const struct s5c73m3_frame_size *oif_pix_size[2];
	u32 mbus_code;

	const struct s5c73m3_interval *fiv;

	struct v4l2_mbus_frame_desc frame_desc;
	/* protects the struct members below */
	struct mutex lock;

	struct s5c73m3_ctrls ctrls;

	u8 streaming:1;
	u8 apply_fmt:1;
	u8 apply_fiv:1;
	u8 isp_ready:1;

	short power;

	char sensor_fw[S5C73M3_SENSOR_FW_LEN + 2];
	char sensor_type[S5C73M3_SENSOR_TYPE_LEN + 2];
	char fw_file_version[2];
	unsigned int fw_size;
};

struct s5c73m3_frame_size {
	u32 width;
	u32 height;
	u8 reg_val;
};

extern int s5c73m3_dbg;

int s5c73m3_register_spi_driver(struct s5c73m3 *state);
void s5c73m3_unregister_spi_driver(struct s5c73m3 *state);
int s5c73m3_spi_write(struct s5c73m3 *state, const void *addr,
		      const unsigned int len, const unsigned int tx_size);
int s5c73m3_spi_read(struct s5c73m3 *state, void *addr,
		      const unsigned int len, const unsigned int tx_size);

int s5c73m3_read(struct s5c73m3 *state, u32 addr, u16 *data);
int s5c73m3_write(struct s5c73m3 *state, u32 addr, u16 data);
int s5c73m3_isp_command(struct s5c73m3 *state, u16 command, u16 data);
int s5c73m3_init_controls(struct s5c73m3 *state);

static inline struct v4l2_subdev *ctrl_to_sensor_sd(struct v4l2_ctrl *ctrl)
{
	return &container_of(ctrl->handler, struct s5c73m3,
			     ctrls.handler)->sensor_sd;
}

static inline struct s5c73m3 *sensor_sd_to_s5c73m3(struct v4l2_subdev *sd)
{
	return container_of(sd, struct s5c73m3, sensor_sd);
}

static inline struct s5c73m3 *oif_sd_to_s5c73m3(struct v4l2_subdev *sd)
{
	return container_of(sd, struct s5c73m3, oif_sd);
}
#endif	/* S5C73M3_H_ */