Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 241776
b: refs/heads/master
c: a25be18
h: refs/heads/master
v: v3
  • Loading branch information
Sylwester Nawrocki authored and Mauro Carvalho Chehab committed Mar 21, 2011
1 parent c3118f2 commit 0587c00
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 43 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ac75934cc644051dc1b33b234448ea4a0990f31f
refs/heads/master: a25be18dfb6e1b172498a9f6c9793d67057000b0
45 changes: 31 additions & 14 deletions trunk/drivers/media/video/s5p-fimc/fimc-capture.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,26 +113,43 @@ static int fimc_subdev_attach(struct fimc_dev *fimc, int index)
return -ENODEV;
}

static int fimc_isp_subdev_init(struct fimc_dev *fimc, int index)
static int fimc_isp_subdev_init(struct fimc_dev *fimc, unsigned int index)
{
struct s5p_fimc_isp_info *isp_info;
int ret;

if (index >= FIMC_MAX_CAMIF_CLIENTS)
return -EINVAL;

isp_info = fimc->pdata->isp_info[index];
if (!isp_info)
return -EINVAL;

if (isp_info->clk_frequency)
clk_set_rate(fimc->clock[CLK_CAM], isp_info->clk_frequency);

ret = clk_enable(fimc->clock[CLK_CAM]);
if (ret)
return ret;

ret = fimc_subdev_attach(fimc, index);
if (ret)
return ret;

isp_info = fimc->pdata->isp_info[fimc->vid_cap.input_index];
ret = fimc_hw_set_camera_polarity(fimc, isp_info);
if (!ret) {
ret = v4l2_subdev_call(fimc->vid_cap.sd, core,
s_power, 1);
if (!ret)
return ret;
}
if (ret)
return ret;

ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 1);
if (!ret)
return ret;

/* enabling power failed so unregister subdev */
fimc_subdev_unregister(fimc);
err("ISP initialization failed: %d", ret);

v4l2_err(&fimc->vid_cap.v4l2_dev, "ISP initialization failed: %d\n",
ret);

return ret;
}

Expand Down Expand Up @@ -190,10 +207,7 @@ static int fimc_stop_capture(struct fimc_dev *fimc)
test_bit(ST_CAPT_SHUT, &fimc->state),
FIMC_SHUTDOWN_TIMEOUT);

ret = v4l2_subdev_call(cap->sd, video, s_stream, 0);

if (ret && ret != -ENOIOCTLCMD)
v4l2_err(&fimc->vid_cap.v4l2_dev, "s_stream(0) failed\n");
v4l2_subdev_call(cap->sd, video, s_stream, 0);

spin_lock_irqsave(&fimc->slock, flags);
fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND |
Expand Down Expand Up @@ -408,7 +422,7 @@ static int fimc_capture_open(struct file *file)
return -EBUSY;

if (++fimc->vid_cap.refcnt == 1) {
ret = fimc_isp_subdev_init(fimc, -1);
ret = fimc_isp_subdev_init(fimc, 0);
if (ret) {
fimc->vid_cap.refcnt--;
return -EIO;
Expand All @@ -433,6 +447,7 @@ static int fimc_capture_close(struct file *file)
v4l2_err(&fimc->vid_cap.v4l2_dev, "releasing ISP\n");

v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0);
clk_disable(fimc->clock[CLK_CAM]);
fimc_subdev_unregister(fimc);
}

Expand Down Expand Up @@ -604,6 +619,8 @@ static int fimc_cap_s_input(struct file *file, void *priv,
int ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0);
if (ret)
err("s_power failed: %d", ret);

clk_disable(fimc->clock[CLK_CAM]);
}

/* Release the attached sensor subdevice. */
Expand Down
59 changes: 36 additions & 23 deletions trunk/drivers/media/video/s5p-fimc/fimc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@

#include "fimc-core.h"

static char *fimc_clock_name[NUM_FIMC_CLOCKS] = { "sclk_fimc", "fimc" };
static char *fimc_clocks[MAX_FIMC_CLOCKS] = {
"sclk_fimc", "fimc", "sclk_cam"
};

static struct fimc_fmt fimc_formats[] = {
{
Expand Down Expand Up @@ -1478,7 +1480,7 @@ static void fimc_unregister_m2m_device(struct fimc_dev *fimc)
static void fimc_clk_release(struct fimc_dev *fimc)
{
int i;
for (i = 0; i < NUM_FIMC_CLOCKS; i++) {
for (i = 0; i < fimc->num_clocks; i++) {
if (fimc->clock[i]) {
clk_disable(fimc->clock[i]);
clk_put(fimc->clock[i]);
Expand All @@ -1489,15 +1491,16 @@ static void fimc_clk_release(struct fimc_dev *fimc)
static int fimc_clk_get(struct fimc_dev *fimc)
{
int i;
for (i = 0; i < NUM_FIMC_CLOCKS; i++) {
fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clock_name[i]);
if (IS_ERR(fimc->clock[i])) {
dev_err(&fimc->pdev->dev,
"failed to get fimc clock: %s\n",
fimc_clock_name[i]);
return -ENXIO;
for (i = 0; i < fimc->num_clocks; i++) {
fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]);

if (!IS_ERR_OR_NULL(fimc->clock[i])) {
clk_enable(fimc->clock[i]);
continue;
}
clk_enable(fimc->clock[i]);
dev_err(&fimc->pdev->dev, "failed to get fimc clock: %s\n",
fimc_clocks[i]);
return -ENXIO;
}
return 0;
}
Expand All @@ -1508,6 +1511,7 @@ static int fimc_probe(struct platform_device *pdev)
struct resource *res;
struct samsung_fimc_driverdata *drv_data;
int ret = 0;
int cap_input_index = -1;

dev_dbg(&pdev->dev, "%s():\n", __func__);

Expand Down Expand Up @@ -1557,10 +1561,26 @@ static int fimc_probe(struct platform_device *pdev)
goto err_req_region;
}

fimc->num_clocks = MAX_FIMC_CLOCKS - 1;
/*
* Check if vide capture node needs to be registered for this device
* instance.
*/
if (fimc->pdata) {
int i;
for (i = 0; i < FIMC_MAX_CAMIF_CLIENTS; ++i)
if (fimc->pdata->isp_info[i])
break;
if (i < FIMC_MAX_CAMIF_CLIENTS) {
cap_input_index = i;
fimc->num_clocks++;
}
}

ret = fimc_clk_get(fimc);
if (ret)
goto err_regs_unmap;
clk_set_rate(fimc->clock[0], drv_data->lclk_frequency);
clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency);

res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
Expand Down Expand Up @@ -1590,19 +1610,12 @@ static int fimc_probe(struct platform_device *pdev)
goto err_irq;

/* At least one camera sensor is required to register capture node */
if (fimc->pdata) {
int i;
for (i = 0; i < FIMC_MAX_CAMIF_CLIENTS; ++i)
if (fimc->pdata->isp_info[i])
break;

if (i < FIMC_MAX_CAMIF_CLIENTS) {
ret = fimc_register_capture_device(fimc);
if (ret)
goto err_m2m;
}
if (cap_input_index >= 0) {
ret = fimc_register_capture_device(fimc);
if (ret)
goto err_m2m;
clk_disable(fimc->clock[CLK_CAM]);
}

/*
* Exclude the additional output DMA address registers by masking
* them out on HW revisions that provide extended capabilites.
Expand Down
18 changes: 13 additions & 5 deletions trunk/drivers/media/video/s5p-fimc/fimc-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,21 @@

/* Time to wait for next frame VSYNC interrupt while stopping operation. */
#define FIMC_SHUTDOWN_TIMEOUT ((100*HZ)/1000)
#define NUM_FIMC_CLOCKS 2
#define MAX_FIMC_CLOCKS 3
#define MODULE_NAME "s5p-fimc"
#define FIMC_MAX_DEVS 4
#define FIMC_MAX_OUT_BUFS 4
#define SCALER_MAX_HRATIO 64
#define SCALER_MAX_VRATIO 64
#define DMA_MIN_SIZE 8

/* FIMC device state flags */
/* indices to the clocks array */
enum {
CLK_BUS,
CLK_GATE,
CLK_CAM,
};

enum fimc_dev_flags {
/* for m2m node */
ST_IDLE,
Expand Down Expand Up @@ -407,7 +413,8 @@ struct fimc_ctx;
* @lock: the mutex protecting this data structure
* @pdev: pointer to the FIMC platform device
* @pdata: pointer to the device platform data
* @id: FIMC device index (0..2)
* @id: FIMC device index (0..FIMC_MAX_DEVS)
* @num_clocks: the number of clocks managed by this device instance
* @clock[]: the clocks required for FIMC operation
* @regs: the mapped hardware registers
* @regs_res: the resource claimed for IO registers
Expand All @@ -423,8 +430,9 @@ struct fimc_dev {
struct platform_device *pdev;
struct s5p_platform_fimc *pdata;
struct samsung_fimc_variant *variant;
int id;
struct clk *clock[NUM_FIMC_CLOCKS];
u16 id;
u16 num_clocks;
struct clk *clock[MAX_FIMC_CLOCKS];
void __iomem *regs;
struct resource *regs_res;
int irq;
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/media/s5p_fimc.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ struct i2c_board_info;
* interace configuration.
*
* @board_info: pointer to I2C subdevice's board info
* @clk_frequency: frequency of the clock the host interface provides to sensor
* @bus_type: determines bus type, MIPI, ITU-R BT.601 etc.
* @i2c_bus_num: i2c control bus id the sensor is attached to
* @mux_id: FIMC camera interface multiplexer index (separate for MIPI and ITU)
* @flags: flags defining bus signals polarity inversion (High by default)
*/
struct s5p_fimc_isp_info {
struct i2c_board_info *board_info;
unsigned long clk_frequency;
enum cam_bus_type bus_type;
u16 i2c_bus_num;
u16 mux_id;
Expand Down

0 comments on commit 0587c00

Please sign in to comment.