if (ret)
goto out_unlock;
- /* restore settings */
- gc0310_res = gc0310_res_preview;
- N_RES = N_RES_PREVIEW;
-
/* restore value of all ctrls */
ret = __v4l2_ctrl_handler_setup(&dev->ctrls.handler);
return gc0310_init(sd);
}
-/* TODO: remove it. */
-static int startup(struct v4l2_subdev *sd)
+static struct v4l2_mbus_framefmt *
+gc0310_get_pad_format(struct gc0310_device *dev,
+ struct v4l2_subdev_state *state,
+ unsigned int pad, enum v4l2_subdev_format_whence which)
{
- struct gc0310_device *dev = to_gc0310_sensor(sd);
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- int ret = 0;
+ if (which == V4L2_SUBDEV_FORMAT_TRY)
+ return v4l2_subdev_get_try_format(&dev->sd, state, pad);
- ret = gc0310_write_reg_array(client, dev->res->regs, dev->res->reg_count);
- if (ret) {
- dev_err(&client->dev, "gc0310 write register err.\n");
- return ret;
- }
+ return &dev->mode.fmt;
+}
- return ret;
+/* The GC0310 currently only supports 1 fixed fmt */
+static void gc0310_fill_format(struct v4l2_mbus_framefmt *fmt)
+{
+ memset(fmt, 0, sizeof(*fmt));
+ fmt->width = GC0310_NATIVE_WIDTH;
+ fmt->height = GC0310_NATIVE_HEIGHT;
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8;
}
static int gc0310_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
- struct v4l2_mbus_framefmt *fmt = &format->format;
- struct gc0310_device *dev = to_gc0310_sensor(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct camera_mipi_info *gc0310_info = NULL;
- struct gc0310_resolution *res;
- int ret = 0;
-
- if (format->pad)
- return -EINVAL;
-
- if (!fmt)
- return -EINVAL;
-
- gc0310_info = v4l2_get_subdev_hostdata(sd);
- if (!gc0310_info)
- return -EINVAL;
-
- mutex_lock(&dev->input_lock);
+ struct gc0310_device *dev = to_gc0310_sensor(sd);
+ struct v4l2_mbus_framefmt *fmt;
+ int ret;
- res = v4l2_find_nearest_size(gc0310_res_preview,
- ARRAY_SIZE(gc0310_res_preview), width,
- height, fmt->width, fmt->height);
- if (!res)
- res = &gc0310_res_preview[N_RES - 1];
+ fmt = gc0310_get_pad_format(dev, sd_state, format->pad, format->which);
+ gc0310_fill_format(fmt);
- fmt->width = res->width;
- fmt->height = res->height;
- dev->res = res;
+ format->format = *fmt;
- fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8;
-
- if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- sd_state->pads->try_fmt = *fmt;
- mutex_unlock(&dev->input_lock);
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
return 0;
- }
+ mutex_lock(&dev->input_lock);
/* s_power has not been called yet for std v4l2 clients (camorama) */
power_up(sd);
-
- dev_dbg(&client->dev, "%s: before gc0310_write_reg_array %s\n",
- __func__, dev->res->desc);
- ret = startup(sd);
- if (ret) {
- dev_err(&client->dev, "gc0310 startup err\n");
- goto err;
- }
-
-err:
+ ret = gc0310_write_reg_array(client, gc0310_VGA_30fps, ARRAY_SIZE(gc0310_VGA_30fps));
mutex_unlock(&dev->input_lock);
+
return ret;
}
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
- struct v4l2_mbus_framefmt *fmt = &format->format;
struct gc0310_device *dev = to_gc0310_sensor(sd);
+ struct v4l2_mbus_framefmt *fmt;
- if (format->pad)
- return -EINVAL;
-
- if (!fmt)
- return -EINVAL;
-
- fmt->width = dev->res->width;
- fmt->height = dev->res->height;
- fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8;
-
+ fmt = gc0310_get_pad_format(dev, sd_state, format->pad, format->which);
+ format->format = *fmt;
return 0;
}
static int gc0310_g_frame_interval(struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval)
{
- struct gc0310_device *dev = to_gc0310_sensor(sd);
-
interval->interval.numerator = 1;
- interval->interval.denominator = dev->res->fps;
+ interval->interval.denominator = GC0310_FPS;
return 0;
}
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
- if (code->index >= MAX_FMTS)
+ /* We support only a single format */
+ if (code->index)
return -EINVAL;
code->code = MEDIA_BUS_FMT_SGRBG8_1X8;
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
- int index = fse->index;
-
- if (index >= N_RES)
+ /* We support only a single resolution */
+ if (fse->index)
return -EINVAL;
- fse->min_width = gc0310_res[index].width;
- fse->min_height = gc0310_res[index].height;
- fse->max_width = gc0310_res[index].width;
- fse->max_height = gc0310_res[index].height;
+ fse->min_width = GC0310_NATIVE_WIDTH;
+ fse->max_width = GC0310_NATIVE_WIDTH;
+ fse->min_height = GC0310_NATIVE_HEIGHT;
+ fse->max_height = GC0310_NATIVE_HEIGHT;
return 0;
}
static int gc0310_g_skip_frames(struct v4l2_subdev *sd, u32 *frames)
{
- struct gc0310_device *dev = to_gc0310_sensor(sd);
-
- mutex_lock(&dev->input_lock);
- *frames = dev->res->skip_frames;
- mutex_unlock(&dev->input_lock);
-
+ *frames = GC0310_SKIP_FRAMES;
return 0;
}
return -ENOMEM;
mutex_init(&dev->input_lock);
-
- dev->res = &gc0310_res_preview[0];
v4l2_i2c_subdev_init(&dev->sd, client, &gc0310_ops);
+ gc0310_fill_format(&dev->mode.fmt);
pdata = gmin_camera_platform_data(&dev->sd,
ATOMISP_INPUT_FORMAT_RAW_8,
dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
dev->pad.flags = MEDIA_PAD_FL_SOURCE;
- dev->format.code = MEDIA_BUS_FMT_SGRBG8_1X8;
dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ret = gc0310_init_controls(dev);
#include "../include/linux/atomisp_platform.h"
-#define GC0310_FOCAL_LENGTH_NUM 278 /*2.78mm*/
+#define GC0310_NATIVE_WIDTH 656
+#define GC0310_NATIVE_HEIGHT 496
-#define MAX_FMTS 1
+#define GC0310_FPS 30
+#define GC0310_SKIP_FRAMES 3
-/*
- * focal length bits definition:
- * bits 31-16: numerator, bits 15-0: denominator
- */
-#define GC0310_FOCAL_LENGTH_DEFAULT 0x1160064
-
-/*
- * current f-number bits definition:
- * bits 31-16: numerator, bits 15-0: denominator
- */
-#define GC0310_F_NUMBER_DEFAULT 0x1a000a
+#define GC0310_FOCAL_LENGTH_NUM 278 /* 2.78mm */
-/*
- * f-number range bits definition:
- * bits 31-24: max f-number numerator
- * bits 23-16: max f-number denominator
- * bits 15-8: min f-number numerator
- * bits 7-0: min f-number denominator
- */
-#define GC0310_F_NUMBER_RANGE 0x1a0a1a0a
#define GC0310_ID 0xa310
#define GC0310_RESET_RELATED 0xFE
#define GC0310_START_STREAMING 0x94 /* 8-bit enable */
#define GC0310_STOP_STREAMING 0x0 /* 8-bit disable */
-#define GC0310_BIN_FACTOR_MAX 3
-
-struct gc0310_resolution {
- u8 *desc;
- const struct gc0310_reg *regs;
- int reg_count;
- int res;
- int width;
- int height;
- int fps;
- int pix_clk_freq;
- u32 skip_frames;
- u16 pixels_per_line;
- u16 lines_per_frame;
- bool used;
-};
-
/*
* gc0310 device structure.
*/
struct gc0310_device {
struct v4l2_subdev sd;
struct media_pad pad;
- struct v4l2_mbus_framefmt format;
struct mutex input_lock;
struct camera_sensor_platform_data *platform_data;
- struct gc0310_resolution *res;
- u8 type;
bool power_on;
+ struct gc0310_mode {
+ struct v4l2_mbus_framefmt fmt;
+ } mode;
+
struct gc0310_ctrls {
struct v4l2_ctrl_handler handler;
struct v4l2_ctrl *exposure;
{ 0xfe, 0x00 },
};
-static struct gc0310_resolution gc0310_res_preview[] = {
- {
- .desc = "gc0310_VGA_30fps",
- .width = 656, // 648,
- .height = 496, // 488,
- .fps = 30,
- //.pix_clk_freq = 73,
- .used = 0,
-#if 0
- .pixels_per_line = 0x0314,
- .lines_per_frame = 0x0213,
-#endif
- .skip_frames = 2,
- .regs = gc0310_VGA_30fps,
- .reg_count = ARRAY_SIZE(gc0310_VGA_30fps),
- },
-};
-
-#define N_RES_PREVIEW (ARRAY_SIZE(gc0310_res_preview))
-
-static struct gc0310_resolution *gc0310_res = gc0310_res_preview;
-static unsigned long N_RES = N_RES_PREVIEW;
#endif