aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/video/samsung/4xa_sensor.c
diff options
context:
space:
mode:
authorWerner Almesberger <werner@openmoko.org>2009-03-05 14:39:51 +0000
committerAndy Green <agreen@octopus.localdomain>2009-03-05 14:39:51 +0000
commit33a321349df772925a696cb454f28e8119d7a554 (patch)
tree8c5fb46b9cadb240f727e89ba64a654b45e3f822 /drivers/media/video/samsung/4xa_sensor.c
parent550bee6974e152230059d341c255b300e2f82d7a (diff)
Add Samsung S5K4BA camera driver
This is the original Samsung S5K4BA camera driver code from the 2.6.21 BSP. The changes that are needed to make this work in 2.6.29 are in the next patch. Signed-off-by: Werner Almesberger <werner@openmoko.org>
Diffstat (limited to 'drivers/media/video/samsung/4xa_sensor.c')
-rw-r--r--drivers/media/video/samsung/4xa_sensor.c349
1 files changed, 349 insertions, 0 deletions
diff --git a/drivers/media/video/samsung/4xa_sensor.c b/drivers/media/video/samsung/4xa_sensor.c
new file mode 100644
index 00000000000..de398edcc69
--- /dev/null
+++ b/drivers/media/video/samsung/4xa_sensor.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2004 Samsung Electronics
+ * SW.LEE <hitchcar@samsung.com>
+ * - based on Russell King : pcf8583.c
+ * - added smdk24a0, smdk2440
+ * - added poseidon (s3c24a0+wavecom)
+ *
+ * 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.
+ *
+ * Driver for FIMC2.x Camera Decoder
+ *
+ */
+
+//#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+//#define CAMIF_DEBUG
+
+#include "../s3c_camif.h"
+#include "4xa_sensor.h"
+
+static struct i2c_driver sensor_driver;
+
+/* This is an abstract CIS sensor for MSDMA input. */
+
+camif_cis_t msdma_input = {
+ itu_fmt: CAMIF_ITU601,
+ order422: CAMIF_CBYCRY, /* another case: YCRYCB */
+ camclk: 44000000, /* for 20 fps: 44MHz, for 12 fps(more stable): 26MHz */
+ source_x: 800,
+ source_y: 600,
+ win_hor_ofst: 0,
+ win_ver_ofst: 0,
+ win_hor_ofst2: 0,
+ win_ver_ofst2: 0,
+ polarity_pclk: 0,
+ polarity_vsync:1,
+ polarity_href: 0,
+ reset_type:CAMIF_EX_RESET_AL,
+ reset_udelay: 5000,
+};
+
+camif_cis_t interlace_input = {
+ itu_fmt: CAMIF_ITU601,
+ order422: CAMIF_CBYCRY, /* another case: YCRYCB */
+ camclk: 44000000, /* for 20 fps: 44MHz, for 12 fps(more stable): 26MHz */
+ source_x: 800,
+ source_y: 600,
+ win_hor_ofst: 0,
+ win_ver_ofst: 0,
+ win_hor_ofst2: 0,
+ win_ver_ofst2: 0,
+ polarity_pclk: 0,
+ polarity_vsync:1,
+ polarity_href: 0,
+ reset_type:CAMIF_EX_RESET_AL,
+ reset_udelay: 5000,
+};
+
+#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
+static camif_cis_t data = {
+ itu_fmt: CAMIF_ITU601,
+ order422: CAMIF_YCBYCR,
+ camclk: 44000000, /* for 20 fps: 44MHz, for 12 fps(more stable): 26MHz */
+ source_x: 800,
+ source_y: 600,
+ win_hor_ofst: 0,
+ win_ver_ofst: 0,
+ win_hor_ofst2: 0,
+ win_ver_ofst2: 0,
+ polarity_pclk: 0,
+ polarity_vsync:1,
+ polarity_href: 0,
+ reset_type:CAMIF_EX_RESET_AL,
+ reset_udelay: 5000,
+};
+
+s5k4xa_t s5k4ba_regs_mirror[S5K4BA_REGS];
+#else
+#error No samsung CIS moudule here !
+#endif
+
+camif_cis_t* get_initialized_cis(void)
+{
+ if (data.init_sensor == 0)
+ return NULL;
+
+ return &data;
+}
+
+#define CAM_ID 0x5a
+
+static unsigned short ignore[] = { I2C_CLIENT_END };
+static unsigned short normal_addr[] = { (CAM_ID >> 1), I2C_CLIENT_END };
+static unsigned short *forces[] = { NULL };
+
+static struct i2c_client_address_data addr_data = {
+ normal_i2c:normal_addr,
+ /* normal_i2c_range:ignore, */
+ probe:ignore,
+ /* probe_range:ignore, */
+ ignore:ignore,
+ /* ignore_range:ignore, */
+ forces:forces,
+};
+
+
+unsigned char sensor_read(struct i2c_client *client, unsigned char subaddr)
+{
+ int ret;
+ unsigned char buf[1];
+ struct i2c_msg msg = { client->addr, 0, 1, buf };
+ buf[0] = subaddr;
+
+ ret = i2c_transfer(client->adapter, &msg, 1) == 1 ? 0 : -EIO;
+ if (ret == -EIO) {
+ printk(" I2C write Error \n");
+ return -EIO;
+ }
+
+ msg.flags = I2C_M_RD;
+ ret = i2c_transfer(client->adapter, &msg, 1) == 1 ? 0 : -EIO;
+
+ return buf[0];
+}
+
+static int
+sensor_write(struct i2c_client *client,
+ unsigned char subaddr, unsigned char val)
+{
+ unsigned char buf[2];
+ struct i2c_msg msg = { client->addr, 0, 2, buf };
+
+ buf[0] = subaddr;
+ buf[1] = val;
+
+ return i2c_transfer(client->adapter, &msg, 1) == 1 ? 0 : -EIO;
+}
+
+#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
+void inline sensor_init(struct i2c_client *sam_client)
+{
+ int i;
+
+ i = (sizeof(s5k4ba_reg)/sizeof(s5k4ba_reg[0]));
+ for (i = 0; i < S5K4BA_INIT_REGS; i++) {
+ sensor_write(sam_client,
+ s5k4ba_reg[i].subaddr, s5k4ba_reg[i].value);
+ }
+}
+#else
+#error No samsung CIS moudule !
+#endif
+
+static int
+s5k4xa_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+ struct i2c_client *c;
+
+ c = kmalloc(sizeof(*c), GFP_KERNEL);
+ if (!c)
+ return -ENOMEM;
+
+ memset(c, 0, sizeof(struct i2c_client));
+
+ strcpy(c->name, "S5K4XA");
+ c->addr = addr;
+ c->adapter = adap;
+ c->driver = &sensor_driver;
+ c->data = &data;
+ data.sensor = c;
+
+ s3c_camif_register_sensor(c);
+
+ return i2c_attach_client(c);
+}
+
+static int sensor_attach_adapter(struct i2c_adapter *adap)
+{
+ s3c_camif_open_sensor(&data);
+ return i2c_probe(adap, &addr_data, s5k4xa_attach);
+}
+
+static int sensor_detach(struct i2c_client *client)
+{
+ i2c_detach_client(client);
+ s3c_camif_unregister_sensor(client);
+ return 0;
+}
+
+/* Purpose:
+ This fucntion only for SVGA Camera : 4BA
+*/
+static int change_sensor_size(struct i2c_client *client, int size)
+{
+ int i;
+
+ switch (size) {
+#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
+ case SENSOR_QSVGA:
+ for (i = 0; i < S5K4BA_QSVGA_REGS; i++) {
+ sensor_write(client, s5k4ba_reg_qsvga[i].subaddr,
+ s5k4ba_reg_qsvga[i].value);
+ }
+ break;
+
+ case SENSOR_SVGA:
+ for (i = 0; i < S5K4BA_SVGA_REGS; i++) {
+ sensor_write(client, s5k4ba_reg_svga[i].subaddr,
+ s5k4ba_reg_svga[i].value);
+ }
+ break;
+#else
+#error No samsung CIS moudule !
+#endif
+ default:
+ panic("4xa_sensor.c: unexpect value \n");
+ }
+
+ return 0;
+}
+
+static int change_sensor_wb(struct i2c_client *client, int type)
+{
+ printk("[ *** Page 0, 4XA Sensor White Balance Mode ***]\n");
+
+#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
+ sensor_write(client, 0xFC, 0x0);
+ sensor_write(client, 0x30, type);
+#endif
+
+ switch(type){
+ case 0:
+ default:
+ printk(" -> AWB auto mode ]\n");
+ break;
+ case 1:
+ printk(" -> Indoor 3100 mode ]\n");
+ break;
+ case 2:
+ printk(" -> Outdoor 5100 mode ]\n");
+ break;
+ case 3:
+ printk(" -> Indoor 2000 mode ]\n");
+ break;
+ case 4:
+ printk(" -> AE/AWB halt ]\n");
+ break;
+ case 5:
+ printk(" -> Cloudy(6000) mode ]\n");
+ break;
+ case 6:
+ printk(" -> Sunny(8000) mode ]\n");
+ break;
+ }
+
+ return 0;
+}
+
+static int
+sensor_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+ switch (cmd) {
+ case SENSOR_INIT:
+ sensor_init(client);
+ printk(KERN_INFO "External Camera initialized\n");
+ break;
+
+ case USER_ADD:
+ break;
+
+ case USER_EXIT:
+ break;
+
+ case SENSOR_QSVGA:
+ change_sensor_size(client, SENSOR_QSVGA);
+ break;
+
+ case SENSOR_VGA:
+ change_sensor_size(client, SENSOR_VGA);
+ break;
+
+ case SENSOR_SVGA:
+ change_sensor_size(client, SENSOR_SVGA);
+ break;
+
+ case SENSOR_SXGA:
+ change_sensor_size(client, SENSOR_SXGA);
+ break;
+
+ case SENSOR_UXGA:
+ change_sensor_size(client, SENSOR_UXGA);
+ break;
+/* Todo
+ case SENSOR_BRIGHTNESS:
+ change_sensor_setting();
+ break;
+*/
+ case SENSOR_WB:
+ printk("[ *** 4XA Sensor White Balance , No mode ***]\n");
+ change_sensor_wb(client, (int) arg);
+ break;
+
+ default:
+ panic("4xa_sensor.c : Unexpect Sensor Command \n");
+ break;
+ }
+
+ return 0;
+}
+
+static struct i2c_driver sensor_driver = {
+ .driver = {
+ .name = "s5k4xa",
+ },
+ .id = I2C_DRIVERID_S5K_4XA,
+ .attach_adapter = sensor_attach_adapter,
+ .detach_client = sensor_detach,
+ .command = sensor_command
+};
+
+static __init int camif_sensor_init(void)
+{
+ return i2c_add_driver(&sensor_driver);
+}
+
+
+static __init void camif_sensor_exit(void)
+{
+ i2c_del_driver(&sensor_driver);
+}
+
+module_init(camif_sensor_init)
+module_exit(camif_sensor_exit)
+
+MODULE_AUTHOR("Jinsung, Yang <jsgood.yang@samsung.com>");
+MODULE_DESCRIPTION("I2C Client Driver For FIMC V4L2 Driver");
+MODULE_LICENSE("GPL");
+