obj-$(CONFIG_VIDEO_CAMERA) += dev_access.o
obj-$(CONFIG_VIDEO_CAMERA) += debugfs.o
obj-$(CONFIG_VIDEO_CAMERA) += virtual.o
+obj-$(CONFIG_VIDEO_CAMERA) += edp.o
obj-$(CONFIG_CAMERA_DEV_AS364X) += as364x.o
obj-$(CONFIG_CAMERA_DEV_IMX135) += imx135.o
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/gpio.h>
+#include <linux/clk.h>
#include <media/nvc.h>
#include <media/camera.h>
}
int camera_dev_parser(
- struct camera_device *cdev, u32 addr, u32 val)
+ struct camera_device *cdev,
+ u32 command, u32 val,
+ struct camera_seq_status *pst)
{
+ int err = 0;
u8 flag = 0;
- switch (addr) {
+ switch (command) {
+ case CAMERA_TABLE_EDP_STATE:
+ err = camera_edp_req(cdev, val);
+ if (pst)
+ pst->status = cdev->edpc.edp_state;
+ if (err < 0)
+ return err;
+ break;
+ case CAMERA_TABLE_INX_CGATE:
+ case CAMERA_TABLE_INX_CLOCK:
+ {
+ struct clk *ck;
+ int idx = val & CAMERA_TABLE_CLOCK_INDEX_MASK;
+
+ idx >>= CAMERA_TABLE_CLOCK_VALUE_BITS;
+ val &= CAMERA_TABLE_CLOCK_VALUE_MASK;
+ if (idx >= cdev->num_clk) {
+ dev_err(cdev->dev,
+ "clock index %d out of range.\n", idx);
+ return -ENODEV;
+ }
+
+ ck = cdev->clks[idx];
+ dev_dbg(cdev->dev, "%s CAMERA_TABLE_INX_CLOCK %d %d, %d %p\n",
+ __func__, idx, val, cdev->num_clk, ck);
+ if (ck) {
+ if (val) {
+ if (command == CAMERA_TABLE_INX_CLOCK)
+ err = clk_set_rate(ck, val * 1000);
+ if (!err)
+ err = clk_prepare_enable(ck);
+ } else
+ clk_disable_unprepare(ck);
+ }
+ if (err)
+ return err;
+ break;
+ }
case CAMERA_TABLE_PWR:
{
struct nvc_regulator *preg;
if (err) {
dev_err(cdev->dev, "%s %s err\n",
__func__, preg->vreg_name);
- return -EFAULT;
+ return -EIO;
}
} else
dev_dbg(cdev->dev, "%s not available\n",
gpio = &cdev->gpios[val];
if (gpio->valid) {
flag = gpio->active_high ? 0xff : 0;
- if (addr != CAMERA_TABLE_GPIO_INX_ACT)
+ if (command != CAMERA_TABLE_GPIO_INX_ACT)
flag = !flag;
gpio_set_value(gpio->gpio, flag & 0x01);
dev_dbg(cdev->dev, "IDX %d(%d) %d\n", val,
}
flag = 0xff;
- if (addr != CAMERA_TABLE_GPIO_ACT)
+ if (command != CAMERA_TABLE_GPIO_ACT)
flag = !flag;
gpio_set_value(val, flag & 0x01);
dev_dbg(cdev->dev,
usleep_range(val, val + 20);
break;
default:
- dev_err(cdev->dev, "unrecognized cmd %x.\n", addr);
+ dev_err(cdev->dev, "unrecognized cmd %x.\n", command);
return -ENODEV;
- break;
}
return 1;
}
-int camera_dev_wr_table(struct camera_device *cdev, struct camera_reg *table)
+int camera_dev_wr_table(
+ struct camera_device *cdev,
+ struct camera_reg *table,
+ struct camera_seq_status *pst)
{
const struct camera_reg *next;
u8 *b_ptr = cdev->i2c_buf;
dev_dbg(cdev->dev, "%s\n", __func__);
if (!cdev->chip) {
- dev_err(cdev->dev, "%s chip?\n", "EMPTY");
- return -EFAULT;
+ dev_err(cdev->dev, "EMPTY chip!\n");
+ return -EEXIST;
}
byte_num = cdev->chip->regmap_cfg.val_bits / 8;
if (byte_num != 1 && byte_num != 2) {
dev_err(cdev->dev,
"unsupported byte length %d.\n", byte_num);
- return -EFAULT;
+ return -ENODEV;
}
for (next = table; next->addr != CAMERA_TABLE_END; next++) {
dev_dbg(cdev->dev, "%x - %x\n", next->addr, next->val);
if (next->addr & CAMERA_INT_MASK) {
- err = camera_dev_parser(cdev, next->addr, next->val);
+ err = camera_dev_parser(
+ cdev, next->addr, next->val, pst);
if (err > 0) { /* special cmd executed */
err = 0;
continue;
}
- if (err < 0) /* this is a real error */
+ if (err < 0) { /* this is a real error */
+ if (pst)
+ pst->idx = (next - table) /
+ sizeof(*table) + 1;
break;
+ }
}
if (!buf_count) {
dev_dbg(dev, "%s %s", __func__, vreg_name);
if (vreg_name == NULL) {
dev_err(dev, "%s NULL regulator name.\n", __func__);
- return -EFAULT;
+ return -ENODEV;
}
reg = regulator_get(dev, vreg_name);
if (unlikely(IS_ERR_OR_NULL(reg))) {
--- /dev/null
+/*
+ * edp.c
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+
+ * This program is distributed in the hope 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.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define CAMERA_DEVICE_INTERNAL
+
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/gpio.h>
+#include <linux/edp.h>
+
+#include <media/nvc.h>
+#include <media/camera.h>
+
+void camera_edp_lowest(struct camera_device *cdev)
+{
+ struct camera_edp_cfg *cam_edp = &cdev->edpc;
+ struct edp_client *edp_client = &cam_edp->edp_client;
+
+ if (!cam_edp->edpc_en)
+ return;
+
+ cam_edp->edp_state = edp_client->num_states - 1;
+ dev_dbg(cdev->dev, "%s %d\n", __func__, cam_edp->edp_state);
+ if (edp_update_client_request(edp_client, cam_edp->edp_state, NULL)) {
+ dev_err(cdev->dev, "THIS IS NOT LIKELY HAPPEN!\n");
+ dev_err(cdev->dev, "UNABLE TO SET LOWEST EDP STATE!\n");
+ }
+}
+
+static void camera_edp_throttle(unsigned int new_state, void *priv_data)
+{
+ struct camera_device *cdev = priv_data;
+
+ if (cdev->edpc.shutdown)
+ cdev->edpc.shutdown(cdev);
+}
+
+void camera_edp_register(struct camera_device *cdev)
+{
+ struct edp_manager *edp_manager;
+ struct camera_edp_cfg *cam_edp = &cdev->edpc;
+ struct edp_client *edp_client = &cam_edp->edp_client;
+ int ret;
+
+ if (!edp_client->num_states) {
+ dev_notice(cdev->dev, "%s: NO edp states defined.\n", __func__);
+ return;
+ }
+ cam_edp->edpc_en = 0;
+
+ snprintf(edp_client->name, sizeof(edp_client->name) - 1, "%x%02x%s",
+ cdev->client->adapter->nr, cdev->client->addr, cdev->name);
+ edp_client->name[EDP_NAME_LEN - 1] = 0;
+ edp_client->private_data = cdev;
+ edp_client->throttle = camera_edp_throttle;
+
+ dev_dbg(cdev->dev, "%s: %s, e0 = %d, p %d\n", __func__,
+ edp_client->name, edp_client->e0_index, edp_client->priority);
+ for (ret = 0; ret < edp_client->num_states; ret++)
+ dev_dbg(cdev->dev, "e%d = %d mA",
+ ret - edp_client->e0_index, edp_client->states[ret]);
+
+ edp_manager = edp_get_manager("battery");
+ if (!edp_manager) {
+ dev_err(cdev->dev, "unable to get edp manager: battery\n");
+ return;
+ }
+
+ ret = edp_register_client(edp_manager, edp_client);
+ if (ret) {
+ dev_err(cdev->dev, "unable to register edp client\n");
+ return;
+ }
+
+ cam_edp->edpc_en = 1;
+ /* set to lowest state at init */
+ camera_edp_lowest(cdev);
+}
+
+int camera_edp_req(struct camera_device *cdev, unsigned new_state)
+{
+ struct camera_edp_cfg *cam_edp = &cdev->edpc;
+ unsigned approved;
+ int ret = 0;
+
+ if (!cam_edp->edpc_en)
+ return 0;
+
+ dev_dbg(cdev->dev, "%s %d\n", __func__, new_state);
+ ret = edp_update_client_request(
+ &cam_edp->edp_client, new_state, &approved);
+ if (ret) {
+ dev_err(cdev->dev, "E state transition failed\n");
+ return ret;
+ }
+
+ cam_edp->edp_state = approved;
+ if (approved > new_state) {
+ dev_err(cdev->dev, "EDP no enough current\n");
+ return -EAGAIN;
+ }
+
+ return 0;
+}
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of_device.h>
+#include <linux/clk.h>
#include <media/nvc.h>
#include <media/camera.h>
struct chip_config {
+ int clk_num;
int gpio_num;
int reg_num;
struct camera_reg *seq_power_on;
static int virtual_update(
struct camera_device *cdev, struct cam_update *upd, int num)
{
- struct nvc_gpio *gpio;
- u32 *pinmux;
int err = 0;
int idx;
mutex_lock(&cdev->mutex);
for (idx = 0; idx < num; idx++) {
switch (upd[idx].type) {
+ case UPDATE_EDP:
+ {
+ struct edp_cfg ec;
+ struct edp_client *pec = &cdev->edpc.edp_client;
+
+ /* update edp throttle seq */
+ if (upd[idx].index == CAMERA_SEQ_FLAG_EDP) {
+ u32 sidx = upd[idx].arg;
+ dev_dbg(cdev->dev, "%s UPDATE_EDP throttle %d\n",
+ __func__, sidx);
+ if (sidx >= NUM_OF_SEQSTACK ||
+ !cdev->seq_stack[sidx]) {
+ dev_err(cdev->dev, "edp index err!\n");
+ err = -ENOENT;
+ break;
+ }
+
+ cdev->edpc.s_throttle = cdev->seq_stack[sidx];
+ break;
+ }
+
+ dev_dbg(cdev->dev, "%s UPDATE_EDP config\n", __func__);
+ if (cdev->edpc.edpc_en) {
+ dev_err(cdev->dev, "edp client already set!\n");
+ err = -EEXIST;
+ break;
+ }
+ if (upd[idx].size != sizeof(ec)) {
+ dev_err(cdev->dev, "Invalid edp cfg size!\n");
+ err = -EINVAL;
+ break;
+ }
+ memset(&ec, 0, sizeof(ec));
+ if (copy_from_user(&ec,
+ (const void __user *)upd[idx].arg,
+ sizeof(ec))) {
+ dev_err(cdev->dev,
+ "%s copy_from_user err line %d\n",
+ __func__, __LINE__);
+ err = -EFAULT;
+ break;
+ }
+ if (ec.num > CAMERA_MAX_EDP_ENTRIES) {
+ dev_err(cdev->dev, "too many estate entries!\n");
+ err = -E2BIG;
+ break;
+ }
+
+ memcpy(cdev->estates, ec.estates,
+ ec.num * sizeof(cdev->estates[0]));
+ pec->states = cdev->estates;
+ pec->num_states = ec.num;
+ pec->e0_index = ec.e0_index;
+ pec->priority = ec.priority;
+ camera_edp_register(cdev);
+ break;
+ }
+ case UPDATE_CLOCK:
+ {
+ struct clk *ck;
+ u8 buf[CAMERA_MAX_NAME_LENGTH];
+
+ if (!cdev->num_clk) {
+ dev_err(cdev->dev, "NO clock needed.\n");
+ err = -ENODEV;
+ break;
+ }
+ if (upd[idx].index >= cdev->num_clk) {
+ dev_err(cdev->dev,
+ "clock index %d out of range.\n",
+ upd[idx].index);
+ err = -ENODEV;
+ break;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ if (copy_from_user(buf,
+ (const void __user *)upd[idx].arg,
+ sizeof(buf) - 1 < upd[idx].size ?
+ sizeof(buf) - 1 : upd[idx].size)) {
+ dev_err(cdev->dev,
+ "%s copy_from_user err line %d\n",
+ __func__, __LINE__);
+ err = -EFAULT;
+ break;
+ }
+
+ dev_dbg(cdev->dev, "%s UPDATE_CLOCK %d of %d, %s\n",
+ __func__, upd[idx].index, cdev->num_clk, buf);
+ ck = devm_clk_get(cdev->dev, buf);
+ if (IS_ERR(ck)) {
+ dev_err(cdev->dev, "%s: get clock %s FAILED.\n",
+ __func__, buf);
+ return PTR_ERR(ck);
+ }
+ cdev->clks[upd[idx].index] = ck;
+ dev_dbg(cdev->dev, "UPDATE_CLOCK: %d %s\n",
+ upd[idx].index, buf);
+ break;
+ }
case UPDATE_PINMUX:
+ {
+ u32 *pinmux;
+
if (!cdev->pinmux_num) {
dev_err(cdev->dev, "NO pinmux available.\n");
err = -ENODEV;
pinmux = &cdev->mclk_disable_idx;
*pinmux = upd[idx].arg;
break;
+ }
case UPDATE_GPIO:
+ {
+ struct nvc_gpio *gpio;
+
if (upd[idx].index >= cdev->num_gpio) {
dev_err(cdev->dev,
"gpio index %d out of range.\n",
gpio->valid = true;
cdev->gpios[upd[idx].index] = *gpio;
break;
+ }
default:
dev_err(cdev->dev,
"unsupported upd type %d\n", upd[idx].type);
return 0;
mutex_lock(&cdev->mutex);
- err = camera_dev_wr_table(cdev, pwr_seq);
+ err = camera_dev_wr_table(cdev, pwr_seq, NULL);
if (!err)
cdev->is_power_on = 1;
mutex_unlock(&cdev->mutex);
return 0;
mutex_lock(&cdev->mutex);
- err = camera_dev_wr_table(cdev, pwr_seq);
+ err = camera_dev_wr_table(cdev, pwr_seq, NULL);
if (!err)
cdev->is_power_on = 0;
mutex_unlock(&cdev->mutex);
return err;
}
+static int virtual_shutdown(struct camera_device *cdev)
+{
+ struct camera_reg *t_seq = cdev->edpc.s_throttle;
+ int err = 0;
+
+ dev_dbg(cdev->dev, "%s %x %p\n",
+ __func__, cdev->is_power_on, t_seq);
+ if (!cdev->is_power_on)
+ return 0;
+
+ if (t_seq) {
+ mutex_lock(&cdev->mutex);
+ err = camera_dev_wr_table(cdev, t_seq, NULL);
+ mutex_unlock(&cdev->mutex);
+ }
+
+ if (!err)
+ err = virtual_power_off(cdev);
+
+ return err;
+}
+
static int virtual_instance_destroy(struct camera_device *cdev)
{
void *buf;
u32 idx;
dev_dbg(cdev->dev, "%s\n", __func__);
- cdev->gpios = kzalloc(c_info->gpio_num * sizeof(struct nvc_gpio) +
- c_info->reg_num * sizeof(struct nvc_regulator),
+ cdev->gpios = kzalloc(c_info->gpio_num * sizeof(*cdev->gpios) +
+ c_info->reg_num * sizeof(*cdev->regs) +
+ c_info->clk_num * sizeof(*cdev->clks),
GFP_KERNEL);
if (cdev->gpios == NULL) {
dev_err(cdev->dev, "%s memory low!\n", __func__);
cdev->pinmux_tbl = ((struct camera_platform_data *)pdata)->pinmux;
cdev->num_gpio = c_info->gpio_num;
cdev->regs = (void *)cdev->gpios +
- c_info->gpio_num * sizeof(struct nvc_gpio);
+ c_info->gpio_num * sizeof(*cdev->gpios);
cdev->num_reg = c_info->reg_num;
+ cdev->clks = (void *)cdev->regs + c_info->reg_num * sizeof(*cdev->regs);
+ cdev->num_clk = c_info->clk_num;
cdev->mclk_enable_idx = CAMDEV_INVALID;
cdev->mclk_disable_idx = CAMDEV_INVALID;
dev_dbg(dev, "%s: %s, bus type %d, addr bits %d, val bits %d\n",
__func__, dev_info->name, dev_info->bus_type,
dev_info->regmap_cfg.addr_bits, dev_info->regmap_cfg.val_bits);
- dev_dbg(dev, "gpios %d, regs %d\n",
- dev_info->gpio_num, dev_info->reg_num);
+ dev_dbg(dev, "gpios %d, regs %d, clks %d\n",
+ dev_info->gpio_num, dev_info->reg_num, dev_info->clk_num);
if (dev_info->name[0] == '\0') {
dev_err(dev, "%s need a device name!\n", __func__);
return -ENODEV;
__func__, dev_info->gpio_num);
}
+ if (dev_info->clk_num >= 5) {
+ dev_notice(dev, "%s WHAT?! Are you sure you need %d clocks?\n",
+ __func__, dev_info->clk_num);
+ }
+
*len = 0;
num = dev_info->reg_num;
nptr = &dev_info->reg_names[0];
u32 idx;
dev_dbg(dev, "%s regulators:\n", __func__);
+ c_info->clk_num = dev_info->clk_num;
c_info->gpio_num = dev_info->gpio_num;
c_info->reg_num = dev_info->reg_num;
rptr += sizeof(*c_info) + sizeof(char *) * c_info->reg_num;
v_chip->release = virtual_instance_destroy,
v_chip->power_on = virtual_power_on,
v_chip->power_off = virtual_power_off,
+ v_chip->shutdown = virtual_shutdown,
v_chip->update = virtual_update,
camera_chip_add(v_chip);
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>
+#include <linux/clk.h>
#include <media/camera.h>
{
struct nvc_param params;
struct camera_device *cdev = cam->cdev;
- struct camera_reg *p_i2c_table;
+ struct camera_reg *p_i2c_table = NULL;
+ struct camera_seq_status seqs;
+ u8 pfree = 0;
int err = 0;
int idx;
dev_dbg(cam->dev, "param: %x, size %d\n", params.param,
params.sizeofvalue);
if (params.param == CAMERA_SEQ_EXIST) {
- if (params.variant >= NUM_OF_SEQSTACK) {
+ idx = params.variant & CAMERA_SEQ_INDEX_MASK;
+ if (idx >= NUM_OF_SEQSTACK) {
dev_err(cam->dev, "%s seq index out of range %d\n",
- __func__, params.variant);
+ __func__, idx);
return -EFAULT;
}
- p_i2c_table = cdev->seq_stack[params.variant];
+ p_i2c_table = cdev->seq_stack[idx];
if (p_i2c_table == NULL) {
dev_err(cam->dev, "%s seq index empty! %d\n",
- __func__, params.variant);
+ __func__, idx);
return -EEXIST;
}
- err = camera_dev_wr_table(cdev, p_i2c_table);
- return err;
+ goto seq_wr_table;
}
p_i2c_table = devm_kzalloc(cdev->dev, params.sizeofvalue, GFP_KERNEL);
__func__, __LINE__);
return -ENOMEM;
}
+ pfree = 1;
if (copy_from_user(p_i2c_table,
(const void __user *)params.p_value, params.sizeofvalue)) {
dev_err(cam->dev, "%s copy_from_user err line %d\n",
__func__, __LINE__);
- devm_kfree(cdev->dev, p_i2c_table);
- return -EFAULT;
+ err = -EFAULT;
+ goto seq_wr_end;
}
switch (params.param) {
for (idx = 0; idx < NUM_OF_SEQSTACK; idx++) {
if (!cdev->seq_stack[idx]) {
cdev->seq_stack[idx] = p_i2c_table;
+ pfree = 0;
break;
}
}
if (idx >= NUM_OF_SEQSTACK) {
dev_err(cam->dev, "%s seq index full!\n", __func__);
- return -EINVAL;
+ err = -EINVAL;
+ goto seq_wr_end;
} else {
+ if (params.variant & CAMERA_SEQ_FLAG_EDP)
+ cdev->edpc.s_throttle = p_i2c_table;
params.variant = idx;
- if (copy_to_user((void __user *)arg,
- (const void *)¶ms, sizeof(params))) {
- dev_err(cam->dev,
- "%s copy_to_user err line %d\n",
- __func__, __LINE__);
- devm_kfree(cdev->dev, p_i2c_table);
- return -EFAULT;
- }
+ goto seq_wr_upd;
}
if (params.param == CAMERA_SEQ_REGISTER_EXEC)
- err |= camera_dev_wr_table(cdev, p_i2c_table);
+ goto seq_wr_table;
break;
case CAMERA_SEQ_EXEC:
- err |= camera_dev_wr_table(cdev, p_i2c_table);
- devm_kfree(cdev->dev, p_i2c_table);
break;
}
+seq_wr_table:
+ if (err < 0)
+ goto seq_wr_end;
+
+ mutex_lock(&cdev->mutex);
+ err = camera_dev_wr_table(cdev, p_i2c_table, &seqs);
+ mutex_unlock(&cdev->mutex);
+ if (err < 0) {
+ params.param = CAMERA_SEQ_STATUS_MASK | seqs.idx;
+ params.variant = seqs.status;
+ }
+
+seq_wr_upd:
+ if (copy_to_user((void __user *)arg,
+ (const void *)¶ms, sizeof(params))) {
+ dev_err(cam->dev, "%s copy_to_user err line %d\n",
+ __func__, __LINE__);
+ err = -EFAULT;
+ }
+
+seq_wr_end:
+ if (pfree)
+ devm_kfree(cdev->dev, p_i2c_table);
return err;
}
-static int camera_dev_power(struct camera_info *cam, unsigned long pwr)
+static int camera_dev_pwr_set(struct camera_info *cam, unsigned long pwr)
{
struct camera_device *cdev = cam->cdev;
struct camera_chip *chip = cdev->chip;
case NVC_PWR_STDBY_OFF:
if (chip->power_off)
err |= chip->power_off(cdev);
+ camera_edp_lowest(cdev);
break;
case NVC_PWR_STDBY:
case NVC_PWR_COMM:
return err;
}
-static int camera_dev_pwrd(struct camera_info *cam, unsigned long arg)
+static int camera_dev_pwr_get(struct camera_info *cam, unsigned long arg)
{
int pwr;
int err = 0;
}
if (cdev->chip)
(cdev->chip->release)(cdev);
- /*if (cdev->regmap)
- regmap_exit(cdev->regmap);*/
if (cdev->dev)
i2c_unregister_device(to_i2c_client(cdev->dev));
- /*for (idx = 0; idx < NUM_OF_SEQSTACK; idx++)
- kfree(cdev->seq_stack[idx]);*/
if (ref_dec)
atomic_dec(&cdev->chip->ref_cnt);
kfree(cdev);
goto add_driver_end;
}
- if (param.sizeofvalue > sizeof(ref_name)) {
+ if (param.sizeofvalue > sizeof(ref_name) - 1) {
dev_err(cam->dev, "%s driver name too long %d\n",
__func__, param.sizeofvalue);
err = -EFAULT;
while (cm && cm->sensor && strlen(cm->sensor->type)) {
dev_dbg(cam->dev, "%s\n", cm->sensor->type);
if (!strcmp(cm->sensor->type, ref_name)) {
+ dev_dbg(cam->dev, "installing %s\n", cm->sensor->type);
client = i2c_new_device(adap, cm->sensor);
if (!client) {
dev_err(cam->dev, "%s add driver %s fail\n",
err = -EFAULT;
break;
}
- if (cm->sensor &&
- strlen(cm->sensor->type)) {
- i2c_new_device(adap, cm->sensor);
- if (!client) {
- dev_err(cam->dev,
- "%s add driver %s fail\n",
- __func__, cm->sensor->type);
- err = -EFAULT;
- break;
- }
- }
if (cm->focuser && strlen(cm->focuser->type)) {
- i2c_new_device(adap, cm->focuser);
+ dev_dbg(cam->dev, "installing %s\n",
+ cm->focuser->type);
+ client = i2c_new_device(adap, cm->focuser);
if (!client) {
dev_err(cam->dev,
"%s add driver %s fail\n",
}
}
if (cm->flash && strlen(cm->flash->type)) {
- i2c_new_device(adap, cm->flash);
+ dev_dbg(cam->dev, "installing %s\n",
+ cm->flash->type);
+ client = i2c_new_device(adap, cm->flash);
if (!client) {
dev_err(cam->dev,
"%s add driver %s fail\n",
break;
case PCLLK_IOCTL_PWR_WR:
/* This is a Guaranteed Level of Service (GLOS) call */
- err = camera_dev_power(cam, arg);
+ err = camera_dev_pwr_set(cam, arg);
break;
case PCLLK_IOCTL_PWR_RD:
- err = camera_dev_pwrd(cam, arg);
+ err = camera_dev_pwr_get(cam, arg);
break;
case PCLLK_IOCTL_UPDATE:
err = camera_update(cam, arg);
#ifdef __KERNEL__
#include <linux/list.h>
#include <linux/miscdevice.h>
+#include <linux/i2c.h>
#include <linux/regmap.h>
+#include <linux/edp.h>
#include <media/nvc.h>
#endif
#define CAMERA_TABLE_GPIO_INX_DEACT (CAMERA_INT_MASK | 33)
#define CAMERA_TABLE_REG_NEW_POWER (CAMERA_INT_MASK | 40)
#define CAMERA_TABLE_INX_POWER (CAMERA_INT_MASK | 41)
+#define CAMERA_TABLE_INX_CLOCK (CAMERA_INT_MASK | 50)
+#define CAMERA_TABLE_INX_CGATE (CAMERA_INT_MASK | 51)
+#define CAMERA_TABLE_EDP_STATE (CAMERA_INT_MASK | 60)
#define CAMERA_TABLE_PWR_FLAG_MASK 0xf0000000
#define CAMERA_TABLE_PWR_FLAG_ON 0x80000000
#define CAMERA_TABLE_PINMUX_FLAG_MASK 0xf0000000
#define CAMERA_TABLE_PINMUX_FLAG_ON 0x80000000
+#define CAMERA_TABLE_CLOCK_VALUE_BITS 24
+#define CAMERA_TABLE_CLOCK_VALUE_MASK \
+ ((u32)(-1) >> (32 - CAMERA_TABLE_CLOCK_VALUE_BITS))
+#define CAMERA_TABLE_CLOCK_INDEX_BITS (32 - CAMERA_TABLE_CLOCK_VALUE_BITS)
+#define CAMERA_TABLE_CLOCK_INDEX_MASK \
+ ((u32)(-1) << (32 - CAMERA_TABLE_CLOCK_INDEX_BITS))
#define PCLLK_IOCTL_CHIP_REG _IOW('o', 100, struct virtual_device)
#define PCLLK_IOCTL_DEV_REG _IOW('o', 104, struct camera_device_info)
#define PCLLK_IOCTL_PARAM_RD _IOWR('o', 141, struct nvc_param)
#define PCLLK_IOCTL_DRV_ADD _IOW('o', 150, struct nvc_param)
+#define CAMERA_MAX_EDP_ENTRIES 16
#define CAMERA_MAX_NAME_LENGTH 32
#define CAMDEV_INVALID 0xffffffff
+#define CAMERA_SEQ_STATUS_MASK 0xf0000000
+#define CAMERA_SEQ_INDEX_MASK 0x0000ffff
+#define CAMERA_SEQ_FLAG_MASK (~CAMERA_SEQ_INDEX_MASK)
+#define CAMERA_SEQ_FLAG_EDP 0x80000000
enum {
CAMERA_SEQ_EXEC,
CAMERA_SEQ_REGISTER_EXEC,
CAMERA_SEQ_REGISTER_ONLY,
CAMERA_SEQ_EXIST,
+ CAMERA_SEQ_MAX_NUM,
};
enum {
CAMERA_DEVICE_TYPE_I2C,
+ CAMERA_DEVICE_TYPE_MAX_NUM,
};
struct camera_device_info {
u8 reserved;
};
+struct edp_cfg {
+ uint estates[CAMERA_MAX_EDP_ENTRIES];
+ uint num;
+ uint e0_index;
+ int priority;
+};
+
#define VIRTUAL_DEV_MAX_REGULATORS 8
#define VIRTUAL_DEV_MAX_GPIOS 8
#define VIRTUAL_REGNAME_SIZE (VIRTUAL_DEV_MAX_REGULATORS * \
struct camera_reg *power_on;
u32 pwr_off_size;
struct camera_reg *power_off;
+ u32 clk_num;
};
enum {
UPDATE_PINMUX,
UPDATE_GPIO,
UPDATE_POWER,
+ UPDATE_CLOCK,
+ UPDATE_EDP,
UPDATE_MAX_NUM,
};
u32 type;
u32 index;
u32 arg;
+ u32 size;
};
struct cam_device_layout {
#define NUM_OF_SEQSTACK 16
#define SIZEOF_I2C_BUF 32
+struct camera_device;
+
struct camera_module {
struct i2c_board_info *sensor;
struct i2c_board_info *focuser;
struct camera_module *modules;
};
+struct camera_edp_cfg {
+ struct edp_client edp_client;
+ unsigned edp_state;
+ u8 edpc_en;
+ struct camera_reg *s_throttle;
+ int (*shutdown)(struct camera_device *cdev);
+};
+
+struct camera_seq_status {
+ u32 idx;
+ u32 status;
+};
+
struct camera_device {
struct list_head list;
u8 name[CAMERA_MAX_NAME_LENGTH];
struct camera_info *cam;
atomic_t in_use;
struct mutex mutex;
+ uint estates[CAMERA_MAX_EDP_ENTRIES];
+ struct camera_edp_cfg edpc;
+ struct clk **clks;
+ u32 num_clk;
struct nvc_regulator *regs;
u32 num_reg;
struct nvc_gpio *gpios;
int (*release)(struct camera_device *cdev);
int (*power_on)(struct camera_device *cdev);
int (*power_off)(struct camera_device *cdev);
+ int (*shutdown)(struct camera_device *cdev);
int (*update)(struct camera_device *cdev,
struct cam_update *upd, int num);
};
size_t size_layout;
};
+/* common functions */
extern int virtual_device_add(
- struct device *dev, unsigned long arg);
-extern int camera_regulator_get(struct device *dev,
- struct nvc_regulator *nvc_reg, char *vreg_name);
+ struct device *, unsigned long
+);
+extern int camera_regulator_get(
+ struct device *, struct nvc_regulator *, char *
+);
+/* device access functions */
extern int camera_dev_parser(
- struct camera_device *cdev, u32 addr, u32 val);
+ struct camera_device *, u32, u32, struct camera_seq_status *
+);
extern int camera_dev_wr_table(
- struct camera_device *cdev, struct camera_reg *table);
+ struct camera_device *, struct camera_reg *, struct camera_seq_status *
+);
extern int camera_dev_rd_table(
- struct camera_device *cdev, struct camera_reg *table);
-
-extern int camera_debugfs_init(struct camera_platform_info *info);
+ struct camera_device *, struct camera_reg *
+);
+
+/* edp functions */
+void camera_edp_register(
+ struct camera_device *
+);
+int camera_edp_req(
+ struct camera_device *, unsigned
+);
+void camera_edp_lowest(
+ struct camera_device *
+);
+
+/* debugfs functions */
+extern int camera_debugfs_init(
+ struct camera_platform_info *
+);
extern int camera_debugfs_remove(void);
#endif