Path: blob/master/drivers/media/video/m5mols/m5mols_controls.c
17745 views
/*1* Controls for M-5MOLS 8M Pixel camera sensor with ISP2*3* Copyright (C) 2011 Samsung Electronics Co., Ltd.4* Author: HeungJun Kim <[email protected]>5*6* Copyright (C) 2009 Samsung Electronics Co., Ltd.7* Author: Dongsoo Nathaniel Kim <[email protected]>8*9* This program is free software; you can redistribute it and/or modify10* it under the terms of the GNU General Public License as published by11* the Free Software Foundation; either version 2 of the License, or12* (at your option) any later version.13*/1415#include <linux/i2c.h>16#include <linux/delay.h>17#include <linux/videodev2.h>18#include <media/v4l2-ctrls.h>1920#include "m5mols.h"21#include "m5mols_reg.h"2223static struct m5mols_scenemode m5mols_default_scenemode[] = {24[REG_SCENE_NORMAL] = {25REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,26REG_CHROMA_ON, 3, REG_EDGE_ON, 5,27REG_AF_NORMAL, REG_FD_OFF,28REG_MCC_NORMAL, REG_LIGHT_OFF, REG_FLASH_OFF,295, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,30},31[REG_SCENE_PORTRAIT] = {32REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,33REG_CHROMA_ON, 3, REG_EDGE_ON, 4,34REG_AF_NORMAL, BIT_FD_EN | BIT_FD_DRAW_FACE_FRAME,35REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,366, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,37},38[REG_SCENE_LANDSCAPE] = {39REG_AE_ALL, REG_AE_INDEX_00, REG_AWB_AUTO, 0,40REG_CHROMA_ON, 4, REG_EDGE_ON, 6,41REG_AF_NORMAL, REG_FD_OFF,42REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,436, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,44},45[REG_SCENE_SPORTS] = {46REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,47REG_CHROMA_ON, 3, REG_EDGE_ON, 5,48REG_AF_NORMAL, REG_FD_OFF,49REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,506, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,51},52[REG_SCENE_PARTY_INDOOR] = {53REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,54REG_CHROMA_ON, 4, REG_EDGE_ON, 5,55REG_AF_NORMAL, REG_FD_OFF,56REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,576, REG_ISO_200, REG_CAP_NONE, REG_WDR_OFF,58},59[REG_SCENE_BEACH_SNOW] = {60REG_AE_CENTER, REG_AE_INDEX_10_POS, REG_AWB_AUTO, 0,61REG_CHROMA_ON, 4, REG_EDGE_ON, 5,62REG_AF_NORMAL, REG_FD_OFF,63REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,646, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,65},66[REG_SCENE_SUNSET] = {67REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,68REG_AWB_DAYLIGHT,69REG_CHROMA_ON, 3, REG_EDGE_ON, 5,70REG_AF_NORMAL, REG_FD_OFF,71REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,726, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,73},74[REG_SCENE_DAWN_DUSK] = {75REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,76REG_AWB_FLUORESCENT_1,77REG_CHROMA_ON, 3, REG_EDGE_ON, 5,78REG_AF_NORMAL, REG_FD_OFF,79REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,806, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,81},82[REG_SCENE_FALL] = {83REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,84REG_CHROMA_ON, 5, REG_EDGE_ON, 5,85REG_AF_NORMAL, REG_FD_OFF,86REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,876, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,88},89[REG_SCENE_NIGHT] = {90REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,91REG_CHROMA_ON, 3, REG_EDGE_ON, 5,92REG_AF_NORMAL, REG_FD_OFF,93REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,946, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,95},96[REG_SCENE_AGAINST_LIGHT] = {97REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,98REG_CHROMA_ON, 3, REG_EDGE_ON, 5,99REG_AF_NORMAL, REG_FD_OFF,100REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,1016, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,102},103[REG_SCENE_FIRE] = {104REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,105REG_CHROMA_ON, 3, REG_EDGE_ON, 5,106REG_AF_NORMAL, REG_FD_OFF,107REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,1086, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,109},110[REG_SCENE_TEXT] = {111REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,112REG_CHROMA_ON, 3, REG_EDGE_ON, 7,113REG_AF_MACRO, REG_FD_OFF,114REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,1156, REG_ISO_AUTO, REG_CAP_ANTI_SHAKE, REG_WDR_ON,116},117[REG_SCENE_CANDLE] = {118REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,119REG_CHROMA_ON, 3, REG_EDGE_ON, 5,120REG_AF_NORMAL, REG_FD_OFF,121REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,1226, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,123},124};125126/**127* m5mols_do_scenemode() - Change current scenemode128* @mode: Desired mode of the scenemode129*130* WARNING: The execution order is important. Do not change the order.131*/132int m5mols_do_scenemode(struct m5mols_info *info, u8 mode)133{134struct v4l2_subdev *sd = &info->sd;135struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode];136int ret;137138if (mode > REG_SCENE_CANDLE)139return -EINVAL;140141ret = m5mols_lock_3a(info, false);142if (!ret)143ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode);144if (!ret)145ret = m5mols_write(sd, AE_EV_PRESET_CAPTURE, mode);146if (!ret)147ret = m5mols_write(sd, AE_MODE, scenemode.metering);148if (!ret)149ret = m5mols_write(sd, AE_INDEX, scenemode.ev_bias);150if (!ret)151ret = m5mols_write(sd, AWB_MODE, scenemode.wb_mode);152if (!ret)153ret = m5mols_write(sd, AWB_MANUAL, scenemode.wb_preset);154if (!ret)155ret = m5mols_write(sd, MON_CHROMA_EN, scenemode.chroma_en);156if (!ret)157ret = m5mols_write(sd, MON_CHROMA_LVL, scenemode.chroma_lvl);158if (!ret)159ret = m5mols_write(sd, MON_EDGE_EN, scenemode.edge_en);160if (!ret)161ret = m5mols_write(sd, MON_EDGE_LVL, scenemode.edge_lvl);162if (!ret && is_available_af(info))163ret = m5mols_write(sd, AF_MODE, scenemode.af_range);164if (!ret && is_available_af(info))165ret = m5mols_write(sd, FD_CTL, scenemode.fd_mode);166if (!ret)167ret = m5mols_write(sd, MON_TONE_CTL, scenemode.tone);168if (!ret)169ret = m5mols_write(sd, AE_ISO, scenemode.iso);170if (!ret)171ret = m5mols_mode(info, REG_CAPTURE);172if (!ret)173ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr);174if (!ret)175ret = m5mols_write(sd, CAPP_MCC_MODE, scenemode.mcc);176if (!ret)177ret = m5mols_write(sd, CAPP_LIGHT_CTRL, scenemode.light);178if (!ret)179ret = m5mols_write(sd, CAPP_FLASH_CTRL, scenemode.flash);180if (!ret)181ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode);182if (!ret)183ret = m5mols_mode(info, REG_MONITOR);184185return ret;186}187188static int m5mols_lock_ae(struct m5mols_info *info, bool lock)189{190int ret = 0;191192if (info->lock_ae != lock)193ret = m5mols_write(&info->sd, AE_LOCK,194lock ? REG_AE_LOCK : REG_AE_UNLOCK);195if (!ret)196info->lock_ae = lock;197198return ret;199}200201static int m5mols_lock_awb(struct m5mols_info *info, bool lock)202{203int ret = 0;204205if (info->lock_awb != lock)206ret = m5mols_write(&info->sd, AWB_LOCK,207lock ? REG_AWB_LOCK : REG_AWB_UNLOCK);208if (!ret)209info->lock_awb = lock;210211return ret;212}213214/* m5mols_lock_3a() - Lock 3A(Auto Exposure, Auto Whitebalance, Auto Focus) */215int m5mols_lock_3a(struct m5mols_info *info, bool lock)216{217int ret;218219ret = m5mols_lock_ae(info, lock);220if (!ret)221ret = m5mols_lock_awb(info, lock);222/* Don't need to handle unlocking AF */223if (!ret && is_available_af(info) && lock)224ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);225226return ret;227}228229/* m5mols_set_ctrl() - The main s_ctrl function called by m5mols_set_ctrl() */230int m5mols_set_ctrl(struct v4l2_ctrl *ctrl)231{232struct v4l2_subdev *sd = to_sd(ctrl);233struct m5mols_info *info = to_m5mols(sd);234int ret;235236switch (ctrl->id) {237case V4L2_CID_ZOOM_ABSOLUTE:238return m5mols_write(sd, MON_ZOOM, ctrl->val);239240case V4L2_CID_EXPOSURE_AUTO:241ret = m5mols_lock_ae(info,242ctrl->val == V4L2_EXPOSURE_AUTO ? false : true);243if (!ret && ctrl->val == V4L2_EXPOSURE_AUTO)244ret = m5mols_write(sd, AE_MODE, REG_AE_ALL);245if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL) {246int val = info->exposure->val;247ret = m5mols_write(sd, AE_MODE, REG_AE_OFF);248if (!ret)249ret = m5mols_write(sd, AE_MAN_GAIN_MON, val);250if (!ret)251ret = m5mols_write(sd, AE_MAN_GAIN_CAP, val);252}253return ret;254255case V4L2_CID_AUTO_WHITE_BALANCE:256ret = m5mols_lock_awb(info, ctrl->val ? false : true);257if (!ret)258ret = m5mols_write(sd, AWB_MODE, ctrl->val ?259REG_AWB_AUTO : REG_AWB_PRESET);260return ret;261262case V4L2_CID_SATURATION:263ret = m5mols_write(sd, MON_CHROMA_LVL, ctrl->val);264if (!ret)265ret = m5mols_write(sd, MON_CHROMA_EN, REG_CHROMA_ON);266return ret;267268case V4L2_CID_COLORFX:269/*270* This control uses two kinds of registers: normal & color.271* The normal effect belongs to category 1, while the color272* one belongs to category 2.273*274* The normal effect uses one register: CAT1_EFFECT.275* The color effect uses three registers:276* CAT2_COLOR_EFFECT, CAT2_CFIXR, CAT2_CFIXB.277*/278ret = m5mols_write(sd, PARM_EFFECT,279ctrl->val == V4L2_COLORFX_NEGATIVE ? REG_EFFECT_NEGA :280ctrl->val == V4L2_COLORFX_EMBOSS ? REG_EFFECT_EMBOSS :281REG_EFFECT_OFF);282if (!ret)283ret = m5mols_write(sd, MON_EFFECT,284ctrl->val == V4L2_COLORFX_SEPIA ?285REG_COLOR_EFFECT_ON : REG_COLOR_EFFECT_OFF);286if (!ret)287ret = m5mols_write(sd, MON_CFIXR,288ctrl->val == V4L2_COLORFX_SEPIA ?289REG_CFIXR_SEPIA : 0);290if (!ret)291ret = m5mols_write(sd, MON_CFIXB,292ctrl->val == V4L2_COLORFX_SEPIA ?293REG_CFIXB_SEPIA : 0);294return ret;295}296297return -EINVAL;298}299300301