From: Vaibhav Hiremat <hvaibhav@xxxxxx> OMAP: CAM: ISP: Resizer Wrapper Fixes This patch adds the following changes: - Resizer Multipass support - Multiple fixes done by MMS - Moved header file to include/linux folder Signed-off-by: Vaibhav Hiremat <hvaibhav@xxxxxx> Signed-off-by: Sergio Aguirre <saaguirre@xxxxxx> --- drivers/media/video/isp/omap_resizer.c | 963 ++++++++++++++++++++++----------- drivers/media/video/isp/omap_resizer.h | 318 ---------- include/linux/omap_resizer.h | 136 ++++ 3 files changed, 793 insertions(+), 624 deletions(-) Index: omapkernel/drivers/media/video/isp/omap_resizer.c =================================================================== --- omapkernel.orig/drivers/media/video/isp/omap_resizer.c 2008-10-14 10:04:34.000000000 -0500 +++ omapkernel/drivers/media/video/isp/omap_resizer.c 2008-10-14 10:21:13.000000000 -0500 @@ -35,20 +35,197 @@ #include "ispmmu.h" #include "ispreg.h" #include "ispresizer.h" -#include "omap_resizer.h" +#include <linux/omap_resizer.h> #define OMAP_REZR_NAME "omap-resizer" -static struct device_params *device_config; -static struct device *rsz_device; +/* Defines and Constants*/ +#define MAX_CHANNELS 16 +#define MAX_IMAGE_WIDTH 2047 +#define MAX_IMAGE_WIDTH_HIGH 2047 +#define ALIGNMENT 16 +#define CHANNEL_BUSY 1 +#define CHANNEL_FREE 0 +#define PIXEL_EVEN 2 +#define RATIO_MULTIPLIER 256 +/* Bit position Macro */ +/* macro for bit set and clear */ +#define BITSET(variable, bit) ((variable) | (1 << bit)) +#define BITRESET(variable, bit) ((variable) & ~(0x00000001 << (bit))) +#define SET_BIT_INPUTRAM 28 +#define SET_BIT_CBLIN 29 +#define SET_BIT_INPTYP 27 +#define SET_BIT_YCPOS 26 +#define INPUT_RAM 1 +#define UP_RSZ_RATIO 64 +#define DOWN_RSZ_RATIO 512 +#define UP_RSZ_RATIO1 513 +#define DOWN_RSZ_RATIO1 1024 +#define RSZ_IN_SIZE_VERT_SHIFT 16 +#define MAX_HORZ_PIXEL_8BIT 31 +#define MAX_HORZ_PIXEL_16BIT 15 +#define NUM_PHASES 8 +#define NUM_TAPS 4 +#define NUM_D2PH 4 /* for downsampling * 2+x ~ 4x, + * number of phases + */ +#define NUM_D2TAPS 7 /* for downsampling * 2+x ~ 4x, + * number of taps + */ +#define ALIGN32 32 +#define MAX_COEF_COUNTER 16 +#define COEFF_ADDRESS_OFFSET 0x04 + +/* Global structure which contains information about number of channels + and protection variables */ +struct device_params { + + unsigned char opened; /* state of the device */ + struct completion compl_isr; /* Completion for interrupt */ + struct mutex reszwrap_mutex; /* Semaphore for array */ -static struct rsz_mult multipass; -static int rsz_major = -1; + struct videobuf_queue_ops vbq_ops; /* videobuf queue operations */ +}; -static struct class *rsz_class; -static struct platform_driver omap_resizer_driver; +/* Register mapped structure which contains the every register + information */ +struct resizer_config { + u32 rsz_pcr; /* pcr register mapping + * variable. + */ + u32 rsz_in_start; /* in_start register mapping + * variable. + */ + u32 rsz_in_size; /* in_size register mapping + * variable. + */ + u32 rsz_out_size; /* out_size register mapping + * variable. + */ + u32 rsz_cnt; /* rsz_cnt register mapping + * variable. + */ + u32 rsz_sdr_inadd; /* sdr_inadd register mapping + * variable. + */ + u32 rsz_sdr_inoff; /* sdr_inoff register mapping + * variable. + */ + u32 rsz_sdr_outadd; /* sdr_outadd register mapping + * variable. + */ + u32 rsz_sdr_outoff; /* sdr_outbuff register + * mapping variable. + */ + u32 rsz_coeff_horz[16]; /* horizontal coefficients + * mapping array. + */ + u32 rsz_coeff_vert[16]; /* vertical coefficients + * mapping array. + */ + u32 rsz_yehn; /* yehn(luma)register mapping + * variable. + */ +}; + +struct rsz_mult { + int in_hsize; /* input frame horizontal + * size. + */ + int in_vsize; /* input frame vertical size. + */ + int out_hsize; /* output frame horizontal + * size. + */ + int out_vsize; /* output frame vertical + * size. + */ + int in_pitch; /* offset between two rows of + * input frame. + */ + int out_pitch; /* offset between two rows of + * output frame. + */ + int end_hsize; + int end_vsize; + int num_htap; /* 0 = 7tap; 1 = 4tap */ + int num_vtap; /* 0 = 7tap; 1 = 4tap */ + int active; + int inptyp; + int vrsz; + int hrsz; + int hstph; /* for specifying horizontal + * starting phase. + */ + int vstph; + int pix_fmt; /* # defined, UYVY or YUYV. */ + int cbilin; /* # defined, filter with luma + * or bi-linear. + */ + u16 tap4filt_coeffs[32]; /* horizontal filter + * coefficients. + */ + u16 tap7filt_coeffs[32]; /* vertical filter + * coefficients. + */ +}; +/* Channel specific structure contains information regarding + the every channel */ +struct channel_config { + struct resizer_config register_config; /* Instance of register set + * mapping structure + */ + int status; /* Specifies whether the + * channel is busy or not + */ + struct mutex chanprotection_mutex; + enum config_done config_state; + u8 input_buf_index; + u8 output_buf_index; -static u32 rsz_bufsize; +}; + +/* per-filehandle data structure */ +struct rsz_fh { + struct rsz_params *params; + struct channel_config *config; + struct rsz_mult *multipass; /* Multipass to support + * resizing ration outside + * of 0.25x to 4x + */ + spinlock_t vbq_lock; /* spinlock for videobuf + * queues. + */ + enum v4l2_buf_type type; + struct videobuf_queue vbq; + struct device_params *device; + + dma_addr_t isp_addr_read; /* Input/Output address */ + dma_addr_t isp_addr_write; /* Input/Output address */ + u32 rsz_bufsize; /* channel specific buffersize + */ +}; + +static struct device_params *device_config; +static struct device *rsz_device; +static int rsz_major = -1; +/* functions declaration */ +static void rsz_hardware_setup(struct channel_config *rsz_conf_chan); +static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *, + struct channel_config *); +static int rsz_get_params(struct rsz_params *, struct channel_config *); +static void rsz_copy_data(struct rsz_mult *multipass, + struct rsz_params *params); +static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1, + void *arg2); +static void rsz_calculate_crop(struct channel_config *rsz_conf_chan, + struct rsz_cropsize *cropsize); +static int rsz_set_multipass(struct rsz_mult *multipass, + struct channel_config *rsz_conf_chan); +static int rsz_set_ratio(struct rsz_mult *multipass, + struct channel_config *rsz_conf_chan); +static void rsz_config_ratio(struct rsz_mult *multipass, + struct channel_config *rsz_conf_chan); /** * rsz_hardware_setup - Sets hardware configuration registers @@ -56,7 +233,7 @@ * * Set hardware configuration registers **/ -void rsz_hardware_setup(struct channel_config *rsz_conf_chan) +static void rsz_hardware_setup(struct channel_config *rsz_conf_chan) { int coeffcounter; int coeffoffset = 0; @@ -107,9 +284,12 @@ * Returns 0 if successful, or -EINVAL if could not set callback for RSZR IRQ * event or the state of the channel is not configured. **/ -int rsz_start(int *arg, struct device_params *device) +int rsz_start(int *arg, struct rsz_fh *fh) { - struct channel_config *rsz_conf_chan = device->config; + struct channel_config *rsz_conf_chan = fh->config; + struct rsz_mult *multipass = fh->multipass; + struct videobuf_queue *q = &fh->vbq; + int ret; if (rsz_conf_chan->config_state) { dev_err(rsz_device, "State not configured \n"); @@ -130,23 +310,42 @@ ispresizer_enable(1); - wait_for_completion_interruptible(&device_config->compl_isr); + ret = wait_for_completion_interruptible(&device_config->compl_isr); + if (ret != 0) { + dev_dbg(rsz_device, "Unexpected exit from " + "wait_for_completion_interruptible\n"); + wait_for_completion(&device_config->compl_isr); + } - if (multipass.active) { - rsz_set_multipass(rsz_conf_chan); + if (multipass->active) { + rsz_set_multipass(multipass, rsz_conf_chan); goto mult; } - if (device->isp_addr_read) { - ispmmu_unmap(device->isp_addr_read); - device->isp_addr_read = 0; - } - if (device->isp_addr_write) { - ispmmu_unmap(device->isp_addr_write); - device->isp_addr_write = 0; + if (fh->isp_addr_read) { + ispmmu_unmap(fh->isp_addr_read); + fh->isp_addr_read = 0; + } + if (fh->isp_addr_write) { + ispmmu_unmap(fh->isp_addr_write); + fh->isp_addr_write = 0; } rsz_conf_chan->status = CHANNEL_FREE; + q->bufs[rsz_conf_chan->input_buf_index]->state = VIDEOBUF_NEEDS_INIT; + q->bufs[rsz_conf_chan->output_buf_index]->state = VIDEOBUF_NEEDS_INIT; + rsz_conf_chan->register_config.rsz_sdr_outadd = 0; + rsz_conf_chan->register_config.rsz_sdr_inadd = 0; + + /* Unmap and free the DMA memory allocated for buffers */ + videobuf_dma_unmap(q, videobuf_to_dma( + q->bufs[rsz_conf_chan->input_buf_index])); + videobuf_dma_unmap(q, videobuf_to_dma( + q->bufs[rsz_conf_chan->output_buf_index])); + videobuf_dma_free(videobuf_to_dma( + q->bufs[rsz_conf_chan->input_buf_index])); + videobuf_dma_free(videobuf_to_dma( + q->bufs[rsz_conf_chan->output_buf_index])); isp_unset_callback(CBK_RESZ_DONE); @@ -161,20 +360,21 @@ * * Returns always 0 **/ -int rsz_set_multipass(struct channel_config *rsz_conf_chan) +static int rsz_set_multipass(struct rsz_mult *multipass, + struct channel_config *rsz_conf_chan) { - multipass.in_hsize = multipass.out_hsize; - multipass.in_vsize = multipass.out_vsize; - multipass.out_hsize = multipass.end_hsize; - multipass.out_vsize = multipass.end_vsize; - - multipass.out_pitch = (multipass.inptyp ? multipass.out_hsize - : (multipass.out_hsize * 2)); - multipass.in_pitch = (multipass.inptyp ? multipass.in_hsize - : (multipass.in_hsize * 2)); + multipass->in_hsize = multipass->out_hsize; + multipass->in_vsize = multipass->out_vsize; + multipass->out_hsize = multipass->end_hsize; + multipass->out_vsize = multipass->end_vsize; + + multipass->out_pitch = (multipass->inptyp ? multipass->out_hsize + : (multipass->out_hsize * 2)); + multipass->in_pitch = (multipass->inptyp ? multipass->in_hsize + : (multipass->in_hsize * 2)); - rsz_set_ratio(rsz_conf_chan); - rsz_config_ratio(rsz_conf_chan); + rsz_set_ratio(multipass, rsz_conf_chan); + rsz_config_ratio(multipass, rsz_conf_chan); rsz_hardware_setup(rsz_conf_chan); return 0; } @@ -185,26 +385,26 @@ * * Copy data **/ -void rsz_copy_data(struct rsz_params *params) +static void rsz_copy_data(struct rsz_mult *multipass, struct rsz_params *params) { int i; - multipass.in_hsize = params->in_hsize; - multipass.in_vsize = params->in_vsize; - multipass.out_hsize = params->out_hsize; - multipass.out_vsize = params->out_vsize; - multipass.end_hsize = params->out_hsize; - multipass.end_vsize = params->out_vsize; - multipass.in_pitch = params->in_pitch; - multipass.out_pitch = params->out_pitch; - multipass.hstph = params->hstph; - multipass.vstph = params->vstph; - multipass.inptyp = params->inptyp; - multipass.pix_fmt = params->pix_fmt; - multipass.cbilin = params->cbilin; + multipass->in_hsize = params->in_hsize; + multipass->in_vsize = params->in_vsize; + multipass->out_hsize = params->out_hsize; + multipass->out_vsize = params->out_vsize; + multipass->end_hsize = params->out_hsize; + multipass->end_vsize = params->out_vsize; + multipass->in_pitch = params->in_pitch; + multipass->out_pitch = params->out_pitch; + multipass->hstph = params->hstph; + multipass->vstph = params->vstph; + multipass->inptyp = params->inptyp; + multipass->pix_fmt = params->pix_fmt; + multipass->cbilin = params->cbilin; for (i = 0; i < 32; i++) { - multipass.tap4filt_coeffs[i] = params->tap4filt_coeffs[i]; - multipass.tap7filt_coeffs[i] = params->tap7filt_coeffs[i]; + multipass->tap4filt_coeffs[i] = params->tap4filt_coeffs[i]; + multipass->tap7filt_coeffs[i] = params->tap7filt_coeffs[i]; } } @@ -217,14 +417,67 @@ * output image size, horizontal and vertical poly-phase filter coefficients, * luma enchancement filter coefficients, etc. **/ -int rsz_set_params(struct rsz_params *params, +static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *params, struct channel_config *rsz_conf_chan) { - rsz_copy_data(params); + int mul = 1; + if ((params->yenh_params.type < 0) || (params->yenh_params.type > 2)) { + dev_err(rsz_device, "rsz_set_params: Wrong yenh type\n"); + return -EINVAL; + } + if ((params->in_vsize <= 0) || (params->in_hsize <= 0) || + (params->out_vsize <= 0) || (params->out_hsize <= 0) || + (params->in_pitch <= 0) || (params->out_pitch <= 0)) { + dev_err(rsz_device, "rsz_set_params: Invalid size params\n"); + return -EINVAL; + } + if ((params->inptyp != RSZ_INTYPE_YCBCR422_16BIT) && + (params->inptyp != RSZ_INTYPE_PLANAR_8BIT)) { + dev_err(rsz_device, "rsz_set_params: Invalid input type\n"); + return -EINVAL; + } + if ((params->pix_fmt != RSZ_PIX_FMT_UYVY) && + (params->pix_fmt != RSZ_PIX_FMT_YUYV)) { + dev_err(rsz_device, "rsz_set_params: Invalid pixel format\n"); + return -EINVAL; + } + if (params->inptyp == RSZ_INTYPE_YCBCR422_16BIT) + mul = 2; + else + mul = 1; + if (params->in_pitch < (params->in_hsize * mul)) { + dev_err(rsz_device, "rsz_set_params: Pitch is incorrect\n"); + return -EINVAL; + } + if (params->out_pitch < (params->out_hsize * mul)) { + dev_err(rsz_device, "rsz_set_params: Out pitch cannot be less" + " than out hsize\n"); + return -EINVAL; + } + /* Output H size should be even */ + if ((params->out_hsize % PIXEL_EVEN) != 0) { + dev_err(rsz_device, "rsz_set_params: Output H size should" + " be even\n"); + return -EINVAL; + } + if (params->horz_starting_pixel < 0) { + dev_err(rsz_device, "rsz_set_params: Horz start pixel cannot" + " be less than zero\n"); + return -EINVAL; + } - if (0 != rsz_set_ratio(rsz_conf_chan)) + rsz_copy_data(multipass, params); + if (0 != rsz_set_ratio(multipass, rsz_conf_chan)) goto err_einval; + if (params->yenh_params.type) { + if ((multipass->num_htap && multipass->out_hsize > + 1280) || + (!multipass->num_htap && multipass->out_hsize > + 640)) + goto err_einval; + } + if (INPUT_RAM) params->vert_starting_pixel = 0; @@ -267,7 +520,7 @@ & ISPRSZ_YENH_SLOP_MASK; } - rsz_config_ratio(rsz_conf_chan); + rsz_config_ratio(multipass, rsz_conf_chan); rsz_conf_chan->config_state = STATE_CONFIGURED; @@ -283,18 +536,19 @@ * Returns 0 if successful, -EINVAL if invalid output size, upscaling ratio is * being requested, or other ratio configuration value is out of bounds **/ -int rsz_set_ratio(struct channel_config *rsz_conf_chan) +static int rsz_set_ratio(struct rsz_mult *multipass, + struct channel_config *rsz_conf_chan) { int alignment = 0; rsz_conf_chan->register_config.rsz_cnt = 0; - if ((multipass.out_hsize > MAX_IMAGE_WIDTH) || - (multipass.out_vsize > MAX_IMAGE_WIDTH)) { + if ((multipass->out_hsize > MAX_IMAGE_WIDTH) || + (multipass->out_vsize > MAX_IMAGE_WIDTH)) { dev_err(rsz_device, "Invalid output size!"); goto err_einval; } - if (multipass.cbilin) { + if (multipass->cbilin) { rsz_conf_chan->register_config.rsz_cnt = BITSET(rsz_conf_chan->register_config.rsz_cnt, SET_BIT_CBLIN); @@ -304,7 +558,7 @@ BITSET(rsz_conf_chan->register_config.rsz_cnt, SET_BIT_INPUTRAM); } - if (multipass.inptyp == RSZ_INTYPE_PLANAR_8BIT) { + if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT) { rsz_conf_chan->register_config.rsz_cnt = BITSET(rsz_conf_chan->register_config.rsz_cnt, SET_BIT_INPTYP); @@ -313,181 +567,184 @@ BITRESET(rsz_conf_chan->register_config. rsz_cnt, SET_BIT_INPTYP); - if (multipass.pix_fmt == RSZ_PIX_FMT_UYVY) { + if (multipass->pix_fmt == RSZ_PIX_FMT_UYVY) { rsz_conf_chan->register_config.rsz_cnt = BITRESET(rsz_conf_chan->register_config. rsz_cnt, SET_BIT_YCPOS); - } else if (multipass.pix_fmt == RSZ_PIX_FMT_YUYV) { + } else if (multipass->pix_fmt == RSZ_PIX_FMT_YUYV) { rsz_conf_chan->register_config.rsz_cnt = BITSET(rsz_conf_chan->register_config. rsz_cnt, SET_BIT_YCPOS); } } - multipass.vrsz = - (multipass.in_vsize * RATIO_MULTIPLIER) / multipass.out_vsize; - multipass.hrsz = - (multipass.in_hsize * RATIO_MULTIPLIER) / multipass.out_hsize; - if (UP_RSZ_RATIO > multipass.vrsz || UP_RSZ_RATIO > multipass.hrsz) { + multipass->vrsz = + (multipass->in_vsize * RATIO_MULTIPLIER) / multipass->out_vsize; + multipass->hrsz = + (multipass->in_hsize * RATIO_MULTIPLIER) / multipass->out_hsize; + if (UP_RSZ_RATIO > multipass->vrsz || UP_RSZ_RATIO > multipass->hrsz) { dev_err(rsz_device, "Upscaling ratio not supported!"); goto err_einval; } - multipass.vrsz = (multipass.in_vsize - NUM_D2TAPS) * RATIO_MULTIPLIER - / (multipass.out_vsize - 1); - multipass.hrsz = ((multipass.in_hsize - NUM_D2TAPS) * RATIO_MULTIPLIER) - / (multipass.out_hsize - 1); + multipass->vrsz = (multipass->in_vsize - NUM_D2TAPS) * RATIO_MULTIPLIER + / (multipass->out_vsize - 1); + multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS) + * RATIO_MULTIPLIER) / + (multipass->out_hsize - 1); - if (multipass.hrsz <= 512) { - multipass.hrsz = (multipass.in_hsize - NUM_TAPS) + if (multipass->hrsz <= 512) { + multipass->hrsz = (multipass->in_hsize - NUM_TAPS) * RATIO_MULTIPLIER - / (multipass.out_hsize - 1); - if (multipass.hrsz < 64) - multipass.hrsz = 64; - if (multipass.hrsz > 512) - multipass.hrsz = 512; - if (multipass.hstph > NUM_PHASES) + / (multipass->out_hsize - 1); + if (multipass->hrsz < 64) + multipass->hrsz = 64; + if (multipass->hrsz > 512) + multipass->hrsz = 512; + if (multipass->hstph > NUM_PHASES) goto err_einval; - multipass.num_tap = 1; - } else if (multipass.hrsz >= 513 && multipass.hrsz <= 1024) { - if (multipass.hstph > NUM_D2PH) + multipass->num_htap = 1; + } else if (multipass->hrsz >= 513 && multipass->hrsz <= 1024) { + if (multipass->hstph > NUM_D2PH) goto err_einval; - multipass.num_tap = 0; + multipass->num_htap = 0; } - if (multipass.vrsz <= 512) { - multipass.vrsz = (multipass.in_vsize - NUM_TAPS) + if (multipass->vrsz <= 512) { + multipass->vrsz = (multipass->in_vsize - NUM_TAPS) * RATIO_MULTIPLIER - / (multipass.out_vsize - 1); - if (multipass.vrsz < 64) - multipass.vrsz = 64; - if (multipass.vrsz > 512) - multipass.vrsz = 512; - if (multipass.vstph > NUM_PHASES) + / (multipass->out_vsize - 1); + if (multipass->vrsz < 64) + multipass->vrsz = 64; + if (multipass->vrsz > 512) + multipass->vrsz = 512; + if (multipass->vstph > NUM_PHASES) goto err_einval; - } else if (multipass.vrsz >= 513 && multipass.vrsz <= 1024) { - if (multipass.vstph > NUM_D2PH) + multipass->num_vtap = 1; + } else if (multipass->vrsz >= 513 && multipass->vrsz <= 1024) { + if (multipass->vstph > NUM_D2PH) goto err_einval; + multipass->num_vtap = 0; } - if ((multipass.in_pitch) % ALIGN32) { + if ((multipass->in_pitch) % ALIGN32) { dev_err(rsz_device, "Invalid input pitch: %d \n", - multipass.in_pitch); + multipass->in_pitch); goto err_einval; } - if ((multipass.out_pitch) % ALIGN32) { + if ((multipass->out_pitch) % ALIGN32) { dev_err(rsz_device, "Invalid output pitch %d \n", - multipass.out_pitch); + multipass->out_pitch); goto err_einval; } - if (multipass.vrsz < 256 && - (multipass.in_vsize < multipass.out_vsize)) { - if (multipass.inptyp == RSZ_INTYPE_PLANAR_8BIT) + if (multipass->vrsz < 256 && + (multipass->in_vsize < multipass->out_vsize)) { + if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT) alignment = ALIGNMENT; - else if (multipass.inptyp == RSZ_INTYPE_YCBCR422_16BIT) + else if (multipass->inptyp == RSZ_INTYPE_YCBCR422_16BIT) alignment = (ALIGNMENT / 2); else dev_err(rsz_device, "Invalid input type\n"); - if (!(((multipass.out_hsize % PIXEL_EVEN) == 0) - && (multipass.out_hsize % alignment) == 0)) { + if (!(((multipass->out_hsize % PIXEL_EVEN) == 0) + && (multipass->out_hsize % alignment) == 0)) { dev_err(rsz_device, "wrong hsize\n"); goto err_einval; } } - if (multipass.hrsz >= 64 && multipass.hrsz <= 1024) { - if (multipass.out_hsize > MAX_IMAGE_WIDTH) { + if (multipass->hrsz >= 64 && multipass->hrsz <= 1024) { + if (multipass->out_hsize > MAX_IMAGE_WIDTH) { dev_err(rsz_device, "wrong width\n"); goto err_einval; } - multipass.active = 0; + multipass->active = 0; - } else if (multipass.hrsz > 1024) { - if (multipass.out_hsize > MAX_IMAGE_WIDTH) { + } else if (multipass->hrsz > 1024) { + if (multipass->out_hsize > MAX_IMAGE_WIDTH) { dev_err(rsz_device, "wrong width\n"); goto err_einval; } - if (multipass.hstph > NUM_D2PH) + if (multipass->hstph > NUM_D2PH) goto err_einval; - multipass.num_tap = 0; - multipass.out_hsize = multipass.in_hsize * 256 / 1024; - if (multipass.out_hsize % ALIGN32) { - multipass.out_hsize += - abs((multipass.out_hsize % ALIGN32) - ALIGN32); + multipass->num_htap = 0; + multipass->out_hsize = multipass->in_hsize * 256 / 1024; + if (multipass->out_hsize % ALIGN32) { + multipass->out_hsize += + abs((multipass->out_hsize % ALIGN32) - ALIGN32); } - multipass.out_pitch = ((multipass.inptyp) ? multipass.out_hsize - : (multipass.out_hsize * 2)); - multipass.hrsz = ((multipass.in_hsize - NUM_D2TAPS) + multipass->out_pitch = ((multipass->inptyp) ? + multipass->out_hsize : + (multipass->out_hsize * 2)); + multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS) * RATIO_MULTIPLIER) - / (multipass.out_hsize - 1); - multipass.active = 1; - + / (multipass->out_hsize - 1); + multipass->active = 1; } - if (multipass.vrsz > 1024) { - if (multipass.out_vsize > MAX_IMAGE_WIDTH_HIGH) { + if (multipass->vrsz > 1024) { + if (multipass->out_vsize > MAX_IMAGE_WIDTH_HIGH) { dev_err(rsz_device, "wrong width\n"); goto err_einval; } - multipass.out_vsize = multipass.in_vsize * 256 / 1024; - multipass.vrsz = ((multipass.in_vsize - NUM_D2TAPS) + multipass->out_vsize = multipass->in_vsize * 256 / 1024; + multipass->vrsz = ((multipass->in_vsize - NUM_D2TAPS) * RATIO_MULTIPLIER) - / (multipass.out_vsize - 1); - multipass.active = 1; - multipass.num_tap = 0; + / (multipass->out_vsize - 1); + multipass->active = 1; + multipass->num_vtap = 0; } rsz_conf_chan->register_config.rsz_out_size = - multipass.out_hsize + multipass->out_hsize & ISPRSZ_OUT_SIZE_HORZ_MASK; rsz_conf_chan->register_config.rsz_out_size |= - (multipass.out_vsize + (multipass->out_vsize << ISPRSZ_OUT_SIZE_VERT_SHIFT) & ISPRSZ_OUT_SIZE_VERT_MASK; rsz_conf_chan->register_config.rsz_sdr_inoff = - multipass.in_pitch + multipass->in_pitch & ISPRSZ_SDR_INOFF_OFFSET_MASK; rsz_conf_chan->register_config.rsz_sdr_outoff = - multipass.out_pitch + multipass->out_pitch & ISPRSZ_SDR_OUTOFF_OFFSET_MASK; - if (multipass.hrsz >= 64 && multipass.hrsz <= 512) { - if (multipass.hstph > NUM_PHASES) + if (multipass->hrsz >= 64 && multipass->hrsz <= 512) { + if (multipass->hstph > NUM_PHASES) goto err_einval; - } else if (multipass.hrsz >= 64 && multipass.hrsz <= 512) { - if (multipass.hstph > NUM_D2PH) + } else if (multipass->hrsz >= 64 && multipass->hrsz <= 512) { + if (multipass->hstph > NUM_D2PH) goto err_einval; } rsz_conf_chan->register_config.rsz_cnt |= - (multipass.hstph + (multipass->hstph << ISPRSZ_CNT_HSTPH_SHIFT) & ISPRSZ_CNT_HSTPH_MASK; - if (multipass.vrsz >= 64 && multipass.hrsz <= 512) { - if (multipass.vstph > NUM_PHASES) + if (multipass->vrsz >= 64 && multipass->hrsz <= 512) { + if (multipass->vstph > NUM_PHASES) goto err_einval; - } else if (multipass.vrsz >= 64 && multipass.vrsz <= 512) { - if (multipass.vstph > NUM_D2PH) + } else if (multipass->vrsz >= 64 && multipass->vrsz <= 512) { + if (multipass->vstph > NUM_D2PH) goto err_einval; } rsz_conf_chan->register_config.rsz_cnt |= - (multipass.vstph + (multipass->vstph << ISPRSZ_CNT_VSTPH_SHIFT) & ISPRSZ_CNT_VSTPH_MASK; rsz_conf_chan->register_config.rsz_cnt |= - (multipass.hrsz - 1) + (multipass->hrsz - 1) & ISPRSZ_CNT_HRSZ_MASK; rsz_conf_chan->register_config.rsz_cnt |= - ((multipass.vrsz - 1) + ((multipass->vrsz - 1) << ISPRSZ_CNT_VRSZ_SHIFT) & ISPRSZ_CNT_VRSZ_MASK; @@ -502,25 +759,26 @@ * * Configure ratio **/ -void rsz_config_ratio(struct channel_config *rsz_conf_chan) +static void rsz_config_ratio(struct rsz_mult *multipass, + struct channel_config *rsz_conf_chan) { int hsize; int vsize; int coeffcounter; - if (multipass.hrsz <= 512) { - hsize = ((32 * multipass.hstph + (multipass.out_hsize - 1) - * multipass.hrsz + 16) >> 8) + 7; + if (multipass->hrsz <= 512) { + hsize = ((32 * multipass->hstph + (multipass->out_hsize - 1) + * multipass->hrsz + 16) >> 8) + 7; } else { - hsize = ((64 * multipass.hstph + (multipass.out_hsize - 1) - * multipass.hrsz + 32) >> 8) + 7; + hsize = ((64 * multipass->hstph + (multipass->out_hsize - 1) + * multipass->hrsz + 32) >> 8) + 7; } - if (multipass.vrsz <= 512) { - vsize = ((32 * multipass.vstph + (multipass.out_vsize - 1) - * multipass.vrsz + 16) >> 8) + 4; + if (multipass->vrsz <= 512) { + vsize = ((32 * multipass->vstph + (multipass->out_vsize - 1) + * multipass->vrsz + 16) >> 8) + 4; } else { - vsize = ((64 * multipass.vstph + (multipass.out_vsize - 1) - * multipass.vrsz + 32) >> 8) + 7; + vsize = ((64 * multipass->vstph + (multipass->out_vsize - 1) + * multipass->vrsz + 32) >> 8) + 7; } rsz_conf_chan->register_config.rsz_in_size = hsize; @@ -530,55 +788,55 @@ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER; coeffcounter++) { - if (multipass.num_tap) { + if (multipass->num_htap) { rsz_conf_chan->register_config. rsz_coeff_horz[coeffcounter] = - (multipass.tap4filt_coeffs[2 + (multipass->tap4filt_coeffs[2 * coeffcounter] & ISPRSZ_HFILT10_COEF0_MASK); rsz_conf_chan->register_config. rsz_coeff_horz[coeffcounter] |= - ((multipass.tap4filt_coeffs[2 + ((multipass->tap4filt_coeffs[2 * coeffcounter + 1] << ISPRSZ_HFILT10_COEF1_SHIFT) & ISPRSZ_HFILT10_COEF1_MASK); } else { rsz_conf_chan->register_config. rsz_coeff_horz[coeffcounter] = - (multipass.tap7filt_coeffs[2 + (multipass->tap7filt_coeffs[2 * coeffcounter] & ISPRSZ_HFILT10_COEF0_MASK); rsz_conf_chan->register_config. rsz_coeff_horz[coeffcounter] |= - ((multipass.tap7filt_coeffs[2 + ((multipass->tap7filt_coeffs[2 * coeffcounter + 1] << ISPRSZ_HFILT10_COEF1_SHIFT) & ISPRSZ_HFILT10_COEF1_MASK); } - if (multipass.num_tap) { + if (multipass->num_vtap) { rsz_conf_chan->register_config. rsz_coeff_vert[coeffcounter] = - (multipass.tap4filt_coeffs[2 + (multipass->tap4filt_coeffs[2 * coeffcounter] & ISPRSZ_VFILT10_COEF0_MASK); rsz_conf_chan->register_config. rsz_coeff_vert[coeffcounter] |= - ((multipass.tap4filt_coeffs[2 + ((multipass->tap4filt_coeffs[2 * coeffcounter + 1] << ISPRSZ_VFILT10_COEF1_SHIFT) & ISPRSZ_VFILT10_COEF1_MASK); } else { rsz_conf_chan->register_config. rsz_coeff_vert[coeffcounter] = - (multipass.tap7filt_coeffs[2 + (multipass->tap7filt_coeffs[2 * coeffcounter] & ISPRSZ_VFILT10_COEF0_MASK); rsz_conf_chan->register_config. rsz_coeff_vert[coeffcounter] |= - ((multipass.tap7filt_coeffs[2 + ((multipass->tap7filt_coeffs[2 * coeffcounter + 1] << ISPRSZ_VFILT10_COEF1_SHIFT) & ISPRSZ_VFILT10_COEF1_MASK); @@ -594,7 +852,7 @@ * Used to get the Resizer hardware settings associated with the * current logical channel represented by fd. **/ -int rsz_get_params(struct rsz_params *params, +static int rsz_get_params(struct rsz_params *params, struct channel_config *rsz_conf_chan) { int coeffcounter; @@ -704,7 +962,7 @@ * * Calculate Crop values **/ -void rsz_calculate_crop(struct channel_config *rsz_conf_chan, +static void rsz_calculate_crop(struct channel_config *rsz_conf_chan, struct rsz_cropsize *cropsize) { int luma_enable; @@ -729,16 +987,27 @@ static void rsz_vbq_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { + int i; struct rsz_fh *fh = q->priv_data; - struct device_params *device = fh->device; - ispmmu_unmap(device->isp_addr_read); - ispmmu_unmap(device->isp_addr_write); - device->isp_addr_read = 0; - device->isp_addr_write = 0; - spin_lock(&device->vbq_lock); + for (i = 0; i < VIDEO_MAX_FRAME; i++) { + struct videobuf_dmabuf *dma = NULL; + if (!q->bufs[i]) + continue; + if (q->bufs[i]->memory != V4L2_MEMORY_MMAP) + continue; + dma = videobuf_to_dma(q->bufs[i]); + videobuf_dma_unmap(q, dma); + videobuf_dma_free(dma); + } + + ispmmu_unmap(fh->isp_addr_read); + ispmmu_unmap(fh->isp_addr_write); + fh->isp_addr_read = 0; + fh->isp_addr_write = 0; + spin_lock(&fh->vbq_lock); vb->state = VIDEOBUF_NEEDS_INIT; - spin_unlock(&device->vbq_lock); + spin_unlock(&fh->vbq_lock); } @@ -755,42 +1024,39 @@ unsigned int *size) { struct rsz_fh *fh = q->priv_data; - struct device_params *device = fh->device; - - u32 bpp = 1; + struct rsz_mult *multipass = fh->multipass; + u32 insize, outsize; - spin_lock(&device->vbq_lock); + spin_lock(&fh->vbq_lock); if (*cnt <= 0) *cnt = VIDEO_MAX_FRAME; if (*cnt > VIDEO_MAX_FRAME) *cnt = VIDEO_MAX_FRAME; - if (*cnt == 1 && (multipass.out_hsize > multipass.in_hsize)) { + + outsize = multipass->out_pitch * multipass->out_vsize; + insize = multipass->in_pitch * multipass->in_vsize; + if (*cnt == 1 && (outsize > insize)) { dev_err(rsz_device, "2 buffers are required for Upscaling " "mode\n"); goto err_einval; } - if (!device->params->in_hsize || !device->params->in_vsize) { + if (!fh->params->in_hsize || !fh->params->in_vsize) { dev_err(rsz_device, "Can't setup buffer size\n"); goto err_einval; } else { - if (device->params->inptyp == RSZ_INTYPE_YCBCR422_16BIT) - bpp = 2; + if (outsize > insize) + *size = outsize; + else + *size = insize; - if (*cnt == 2) { - *size = (bpp * device->params->out_hsize - * device->params->out_vsize); - } else { - *size = (bpp * device->params->in_hsize - * device->params->in_vsize); - } - rsz_bufsize = *size; + fh->rsz_bufsize = *size; } - spin_unlock(&device->vbq_lock); + spin_unlock(&fh->vbq_lock); return 0; err_einval: - spin_unlock(&device->vbq_lock); + spin_unlock(&fh->vbq_lock); return -EINVAL; } @@ -809,31 +1075,31 @@ enum v4l2_field field) { struct rsz_fh *fh = q->priv_data; - struct device_params *device = fh->device; - struct channel_config *rsz_conf_chan = fh->device->config; - int err = -1; - unsigned int isp_addr; + struct channel_config *rsz_conf_chan = fh->config; + struct rsz_mult *multipass = fh->multipass; + int err = 0; + unsigned int isp_addr, insize, outsize; struct videobuf_dmabuf *dma = videobuf_to_dma(vb); - spin_lock(&device->vbq_lock); + spin_lock(&fh->vbq_lock); if (vb->baddr) { - vb->size = rsz_bufsize; - vb->bsize = rsz_bufsize; + vb->size = fh->rsz_bufsize; + vb->bsize = fh->rsz_bufsize; } else { - spin_unlock(&device->vbq_lock); + spin_unlock(&fh->vbq_lock); dev_err(rsz_device, "No user buffer allocated\n"); goto out; } if (vb->i) { - vb->width = device->params->out_hsize; - vb->height = device->params->out_vsize; + vb->width = fh->params->out_hsize; + vb->height = fh->params->out_vsize; } else { - vb->width = device->params->in_hsize; - vb->height = device->params->in_vsize; + vb->width = fh->params->in_hsize; + vb->height = fh->params->in_vsize; } vb->field = field; - spin_unlock(&device->vbq_lock); + spin_unlock(&fh->vbq_lock); if (vb->state == VIDEOBUF_NEEDS_INIT) { err = videobuf_iolock(q, vb, NULL); @@ -846,18 +1112,27 @@ rsz_conf_chan->register_config. rsz_sdr_outadd = isp_addr; - device->isp_addr_write = isp_addr; + fh->isp_addr_write = isp_addr; + rsz_conf_chan->output_buf_index = vb->i; } else { rsz_conf_chan->register_config. rsz_sdr_inadd = isp_addr; - if (multipass.out_hsize - < multipass.in_hsize) + rsz_conf_chan->input_buf_index = vb->i; + outsize = multipass->out_pitch * + multipass->out_vsize; + insize = multipass->in_pitch * + multipass->in_vsize; + if (outsize < insize) { rsz_conf_chan->register_config. rsz_sdr_outadd = isp_addr; + rsz_conf_chan-> + output_buf_index = + vb->i; + } - device->isp_addr_read = isp_addr; + fh->isp_addr_read = isp_addr; } } } @@ -865,9 +1140,9 @@ } if (!err) { - spin_lock(&device->vbq_lock); + spin_lock(&fh->vbq_lock); vb->state = VIDEOBUF_PREPARED; - spin_unlock(&device->vbq_lock); + spin_unlock(&fh->vbq_lock); flush_cache_user_range(NULL, vb->baddr, (vb->baddr + vb->bsize)); } else @@ -893,59 +1168,79 @@ **/ static int rsz_open(struct inode *inode, struct file *filp) { + int ret = 0; struct channel_config *rsz_conf_chan; struct rsz_fh *fh; struct device_params *device = device_config; struct rsz_params *params; + struct rsz_mult *multipass; - if (filp->f_flags == O_NONBLOCK) - return -1; - - if (device->opened || filp->f_flags & O_NONBLOCK) { - dev_err(rsz_device, "resizer_open: device is already opened\n"); - return -EBUSY; + if ((filp->f_flags & O_NONBLOCK) == O_NONBLOCK) { + printk(KERN_DEBUG "omap-resizer: Device is opened in " + "non blocking mode\n"); + } else { + printk(KERN_DEBUG "omap-resizer: Device is opened in blocking " + "mode\n"); } fh = kzalloc(sizeof(struct rsz_fh), GFP_KERNEL); if (NULL == fh) - goto err_enomem; + return -ENOMEM; isp_get(); rsz_conf_chan = kzalloc(sizeof(struct channel_config), GFP_KERNEL); - if (rsz_conf_chan == NULL) { dev_err(rsz_device, "\n cannot allocate memory to config"); - goto err_enomem; + ret = -ENOMEM; + goto err_enomem0; } params = kzalloc(sizeof(struct rsz_params), GFP_KERNEL); - if (params == NULL) { dev_err(rsz_device, "\n cannot allocate memory to params"); - goto err_enomem; + ret = -ENOMEM; + goto err_enomem1; } - - device->params = params; - device->config = rsz_conf_chan; - device->opened = 1; + multipass = kzalloc(sizeof(struct rsz_mult), GFP_KERNEL); + if (multipass == NULL) { + dev_err(rsz_device, "\n cannot allocate memory to multipass"); + ret = -ENOMEM; + goto err_enomem2; + } + + fh->multipass = multipass; + fh->params = params; + fh->config = rsz_conf_chan; + + if (mutex_lock_interruptible(&device->reszwrap_mutex)) { + ret = -EINTR; + goto err_enomem2; + } + device->opened++; + mutex_unlock(&device->reszwrap_mutex); rsz_conf_chan->config_state = STATE_NOT_CONFIGURED; + rsz_conf_chan->status = CHANNEL_FREE; filp->private_data = fh; fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fh->device = device; videobuf_queue_sg_init(&fh->vbq, &device->vbq_ops, NULL, - &device->vbq_lock, fh->type, + &fh->vbq_lock, fh->type, V4L2_FIELD_NONE, sizeof(struct videobuf_buffer), fh); - init_completion(&device->compl_isr); - mutex_init(&device->reszwrap_mutex); + spin_lock_init(&fh->vbq_lock); mutex_init(&rsz_conf_chan->chanprotection_mutex); return 0; -err_enomem: - return -ENOMEM; +err_enomem2: + kfree(params); +err_enomem1: + kfree(rsz_conf_chan); +err_enomem0: + kfree(fh); + return ret; } /** @@ -957,30 +1252,35 @@ **/ static int rsz_release(struct inode *inode, struct file *filp) { - int ret = 0; + u32 timeout = 0; struct rsz_fh *fh = filp->private_data; - struct device_params *device = fh->device; - struct channel_config *rsz_conf_chan = device->config; - struct rsz_params *params = device->params; + struct channel_config *rsz_conf_chan = fh->config; + struct rsz_params *params = fh->params; + struct rsz_mult *multipass = fh->multipass; struct videobuf_queue *q = &fh->vbq; - ret = mutex_trylock(&rsz_conf_chan->chanprotection_mutex); - if (ret != 1) { - dev_err(rsz_device, "Channel in use\n"); - return -EBUSY; - } - device->opened = 0; - device->params = NULL; - device->config = NULL; + while ((rsz_conf_chan->status != CHANNEL_FREE) && (timeout < 20)) { + timeout++; + schedule(); + } + if (mutex_lock_interruptible(&device_config->reszwrap_mutex)) + return -EINTR; + device_config->opened--; + mutex_unlock(&device_config->reszwrap_mutex); + /* This will Free memory allocated to the buffers, + * and flushes the queue + */ + videobuf_queue_cancel(q); + fh->params = NULL; + fh->config = NULL; - videobuf_mmap_free(q); - rsz_bufsize = 0; + fh->rsz_bufsize = 0; filp->private_data = NULL; kfree(rsz_conf_chan); - kfree(fh); kfree(params); - mutex_unlock(&rsz_conf_chan->chanprotection_mutex); + kfree(multipass); + kfree(fh); isp_put(); @@ -1020,15 +1320,7 @@ int ret = 0; struct rsz_fh *fh = file->private_data; struct device_params *device = fh->device; - struct channel_config *rsz_conf_chan = device->config; - struct rsz_params *params = device->params; - struct rsz_status *status; - - ret = mutex_trylock(&rsz_conf_chan->chanprotection_mutex); - if (ret != 1) { - dev_err(rsz_device, "Channel in use\n"); - goto err_ebusy; - } + struct channel_config *rsz_conf_chan = fh->config; if ((_IOC_TYPE(cmd) != RSZ_IOC_BASE) || (_IOC_NR(cmd) > RSZ_IOC_MAXNR)) { @@ -1048,53 +1340,92 @@ switch (cmd) { case RSZ_REQBUF: - if (mutex_lock_interruptible(&device->reszwrap_mutex)) + { + struct v4l2_requestbuffers req_buf; + if (copy_from_user(&req_buf, (struct v4l2_requestbuffers *)arg, + sizeof(struct v4l2_requestbuffers))) { + goto err_efault; + } + if (mutex_lock_interruptible(&rsz_conf_chan-> + chanprotection_mutex)) goto err_eintr; - ret = videobuf_reqbufs(&fh->vbq, (void *)arg); - mutex_unlock(&device->reszwrap_mutex); + ret = videobuf_reqbufs(&fh->vbq, (void *)&req_buf); + mutex_unlock(&rsz_conf_chan->chanprotection_mutex); break; - + } case RSZ_QUERYBUF: - if (mutex_lock_interruptible(&device->reszwrap_mutex)) + { + struct v4l2_buffer buf; + if (copy_from_user(&buf, (struct v4l2_buffer *)arg, + sizeof(struct v4l2_buffer))) { + goto err_efault; + } + if (mutex_lock_interruptible(&rsz_conf_chan-> + chanprotection_mutex)) goto err_eintr; - ret = videobuf_querybuf(&fh->vbq, (void *)arg); - mutex_unlock(&device->reszwrap_mutex); + ret = videobuf_querybuf(&fh->vbq, (void *)&buf); + mutex_unlock(&rsz_conf_chan->chanprotection_mutex); + if (copy_to_user((struct v4l2_buffer *)arg, &buf, + sizeof(struct v4l2_buffer))) + ret = -EFAULT; break; - + } case RSZ_QUEUEBUF: - if (mutex_lock_interruptible(&device->reszwrap_mutex)) + { + struct v4l2_buffer buf; + if (copy_from_user(&buf, (struct v4l2_buffer *)arg, + sizeof(struct v4l2_buffer))) { + goto err_efault; + } + if (mutex_lock_interruptible(&rsz_conf_chan-> + chanprotection_mutex)) goto err_eintr; - ret = videobuf_qbuf(&fh->vbq, (void *)arg); - mutex_unlock(&device->reszwrap_mutex); + ret = videobuf_qbuf(&fh->vbq, (void *)&buf); + mutex_unlock(&rsz_conf_chan->chanprotection_mutex); break; - + } case RSZ_S_PARAM: - if (mutex_lock_interruptible(&device->reszwrap_mutex)) - goto err_eintr; + { + struct rsz_params *params = fh->params; if (copy_from_user(params, (struct rsz_params *)arg, sizeof(struct rsz_params))) { - mutex_unlock(&device->reszwrap_mutex); goto err_efault; } - mutex_unlock(&device->reszwrap_mutex); - ret = rsz_set_params(params, rsz_conf_chan); + if (mutex_lock_interruptible(&rsz_conf_chan-> + chanprotection_mutex)) + goto err_eintr; + ret = rsz_set_params(fh->multipass, params, rsz_conf_chan); + mutex_unlock(&rsz_conf_chan->chanprotection_mutex); break; - + } case RSZ_G_PARAM: ret = rsz_get_params((struct rsz_params *)arg, rsz_conf_chan); break; case RSZ_G_STATUS: + { + struct rsz_status *status; status = (struct rsz_status *)arg; status->chan_busy = rsz_conf_chan->status; status->hw_busy = ispresizer_busy(); status->src = INPUT_RAM; break; - + } case RSZ_RESIZE: - ret = rsz_start((int *)arg, device); + if (file->f_flags & O_NONBLOCK) { + if (ispresizer_busy()) + return -EBUSY; + else { + if (!mutex_trylock(&device->reszwrap_mutex)) + return -EBUSY; + } + } else { + if (mutex_lock_interruptible(&device->reszwrap_mutex)) + goto err_eintr; + } + ret = rsz_start((int *)arg, fh); + mutex_unlock(&device->reszwrap_mutex); break; - case RSZ_GET_CROPSIZE: rsz_calculate_crop(rsz_conf_chan, (struct rsz_cropsize *)arg); break; @@ -1105,7 +1436,6 @@ } out: - mutex_unlock(&rsz_conf_chan->chanprotection_mutex); return (long)ret; err_minusone: ret = -1; @@ -1113,9 +1443,6 @@ err_eintr: ret = -EINTR; goto out; -err_ebusy: - ret = -EBUSY; - goto out; err_efault: ret = -EFAULT; goto out; @@ -1137,7 +1464,7 @@ * * Interrupt Service Routine for Resizer wrapper **/ -void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2) +static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2) { if ((status & RESZ_DONE) != RESZ_DONE) @@ -1179,6 +1506,9 @@ return 0; } +static struct class *rsz_class; +static struct cdev c_dev; +static dev_t dev; static struct platform_device omap_resizer_device = { .name = OMAP_REZR_NAME, .id = 2, @@ -1204,8 +1534,7 @@ **/ static int __init omap_rsz_init(void) { - - int ret; + int ret = 0; struct device_params *device; device = kzalloc(sizeof(struct device_params), GFP_KERNEL); if (!device) { @@ -1214,35 +1543,54 @@ return -ENOMEM; } - rsz_major = register_chrdev(0, OMAP_REZR_NAME, &rsz_fops); - - if (rsz_major < 0) { - dev_err(rsz_device, OMAP_REZR_NAME ": initialization failed. " - "Could not register " - "character device\n"); + ret = alloc_chrdev_region(&dev, 0, 1, OMAP_REZR_NAME); + if (ret < 0) { + dev_err(rsz_device, OMAP_REZR_NAME ": intialization failed. " + "Could not allocate region " + "for character device\n"); + kfree(device); return -ENODEV; } - ret = platform_driver_register(&omap_resizer_driver); - if (ret) { - dev_err(rsz_device, OMAP_REZR_NAME ": failed to register " - "platform driver!\n"); + /* Register the driver in the kernel */ + /* Initialize of character device */ + cdev_init(&c_dev, &rsz_fops); + c_dev.owner = THIS_MODULE; + c_dev.ops = &rsz_fops; + /* Addding character device */ + ret = cdev_add(&c_dev, dev, 1); + if (ret) { + dev_err(rsz_device, OMAP_REZR_NAME ": Error adding " + "device - %d\n", ret); goto fail2; } + rsz_major = MAJOR(dev); - ret = platform_device_register(&omap_resizer_device); + /* register driver as a platform driver */ + ret = platform_driver_register(&omap_resizer_driver); if (ret) { - dev_err(rsz_device, OMAP_REZR_NAME ": failed to register " - "platform device!\n"); + dev_err(rsz_device, OMAP_REZR_NAME + ": Failed to register platform driver!\n"); goto fail3; } - rsz_class = class_create(THIS_MODULE, OMAP_REZR_NAME); - - if (!rsz_class) + /* Register the drive as a platform device */ + ret = platform_device_register(&omap_resizer_device); + if (ret) { + dev_err(rsz_device, OMAP_REZR_NAME + ": Failed to register platform device!\n"); goto fail4; + } + rsz_class = class_create(THIS_MODULE, OMAP_REZR_NAME); + if (!rsz_class) { + dev_err(rsz_device, OMAP_REZR_NAME + ": Failed to create class!\n"); + goto fail5; + } + + /* make entry in the devfs */ rsz_device = device_create_drvdata(rsz_class, rsz_device, MKDEV(rsz_major, 0), NULL, OMAP_REZR_NAME); @@ -1253,18 +1601,21 @@ device->vbq_ops.buf_prepare = rsz_vbq_prepare; device->vbq_ops.buf_release = rsz_vbq_release; device->vbq_ops.buf_queue = rsz_vbq_queue; - spin_lock_init(&device->vbq_lock); + init_completion(&device->compl_isr); + mutex_init(&device->reszwrap_mutex); device_config = device; return 0; -fail4: +fail5: platform_device_unregister(&omap_resizer_device); -fail3: +fail4: platform_driver_unregister(&omap_resizer_driver); +fail3: + cdev_del(&c_dev); fail2: - unregister_chrdev(rsz_major, OMAP_REZR_NAME); - + unregister_chrdev_region(dev, 1); + kfree(device); return ret; } @@ -1273,13 +1624,13 @@ **/ void __exit omap_rsz_exit(void) { + device_destroy(rsz_class, dev); + class_destroy(rsz_class); platform_device_unregister(&omap_resizer_device); platform_driver_unregister(&omap_resizer_driver); - unregister_chrdev(rsz_major, OMAP_REZR_NAME); - isp_unset_callback(CBK_RESZ_DONE); + cdev_del(&c_dev); + unregister_chrdev_region(dev, 1); kfree(device_config); - rsz_major = -1; - } module_init(omap_rsz_init) Index: omapkernel/drivers/media/video/isp/omap_resizer.h =================================================================== --- omapkernel.orig/drivers/media/video/isp/omap_resizer.h 2008-10-14 10:04:34.000000000 -0500 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,318 +0,0 @@ -/* - * drivers/media/video/isp/omap_resizer.h - * - * Header file for Resizer module wrapper in TI's OMAP3430 ISP - * - * Copyright (C) 2008 Texas Instruments, Inc. - * - * Contributors: - * Sergio Aguirre <saaguirre@xxxxxx> - * Troy Laramy <t-laramy@xxxxxx> - * - * This package 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. - * - * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef OMAP_ISP_RESIZER_WRAP_H -#define OMAP_ISP_RESIZER_WRAP_H - -/* ioctls definition */ -#define RSZ_IOC_BASE 'R' -#define RSZ_IOC_MAXNR 8 - -/*Ioctl options which are to be passed while calling the ioctl*/ -#define RSZ_REQBUF _IOWR(RSZ_IOC_BASE, 1,\ - struct v4l2_requestbuffers) -#define RSZ_QUERYBUF _IOWR(RSZ_IOC_BASE, 2,\ - struct v4l2_buffer) -#define RSZ_S_PARAM _IOWR(RSZ_IOC_BASE, 3,\ - struct rsz_params) -#define RSZ_G_PARAM _IOWR(RSZ_IOC_BASE, 4,\ - struct rsz_params) -#define RSZ_RESIZE _IOWR(RSZ_IOC_BASE, 5, int) -#define RSZ_G_STATUS _IOWR(RSZ_IOC_BASE, 6,\ - struct rsz_status) -#define RSZ_QUEUEBUF _IOWR(RSZ_IOC_BASE, 7,\ - struct v4l2_buffer) -#define RSZ_GET_CROPSIZE _IOWR(RSZ_IOC_BASE, 8,\ - struct rsz_cropsize) - -/* Defines and Constants*/ - -#define MAX_CHANNELS 16 -#define MAX_IMAGE_WIDTH 2047 -#define MAX_IMAGE_WIDTH_HIGH 2047 - -#define ALIGNMENT 16 -#define CHANNEL_BUSY 1 -#define CHANNEL_FREE 0 -#define PIXEL_EVEN 2 -#define RATIO_MULTIPLIER 256 - -/* Bit position Macro */ -#define BITSET(variable, bit) ((variable) | (1 << bit)) -#define BITRESET(variable, bit) ((variable) & ~(0x00000001 << (bit))) -#define SET_BIT_INPUTRAM 28 -#define SET_BIT_CBLIN 29 -#define SET_BIT_INPTYP 27 -#define SET_BIT_YCPOS 26 -#define INPUT_RAM 1 -#define UP_RSZ_RATIO 64 -#define DOWN_RSZ_RATIO 512 -#define UP_RSZ_RATIO1 513 -#define DOWN_RSZ_RATIO1 1024 -#define RSZ_IN_SIZE_VERT_SHIFT 16 -#define MAX_HORZ_PIXEL_8BIT 31 -#define MAX_HORZ_PIXEL_16BIT 15 -#define NUM_PHASES 8 -#define NUM_TAPS 4 -#define NUM_D2PH 4 /* for downsampling - * 2+x ~ 4x, number of phases - */ -#define NUM_D2TAPS 7 /* for downsampling - * 2+x ~ 4x,number of taps - */ -#define ALIGN32 32 -#define MAX_COEF_COUNTER 16 -#define COEFF_ADDRESS_OFFSET 0x04 - -#define RSZ_INTYPE_YCBCR422_16BIT 0 -#define RSZ_INTYPE_PLANAR_8BIT 1 -#define RSZ_PIX_FMT_UYVY 1 /* cb:y:cr:y */ -#define RSZ_PIX_FMT_YUYV 0 /* y:cb:y:cr */ - -enum config_done { - STATE_CONFIGURED, /* Resizer driver configured - * by application. - */ - STATE_NOT_CONFIGURED /* Resizer driver not - * configured by application. - */ -}; - -/* Structure Definitions */ - -/* used to luma enhancement options */ - -struct rsz_yenh { - int type; /* represents luma enable or - * disable. - */ - unsigned char gain; /* represents gain. */ - unsigned char slop; /* represents slop. */ - unsigned char core; /* Represents core value. */ -}; - -/* Conatins all the parameters for resizing. This structure - * is used to configure resiser parameters - */ -struct rsz_params { - int in_hsize; /* input frame horizontal - * size. - */ - int in_vsize; /* input frame vertical size */ - int in_pitch; /* offset between two rows of - * input frame. - */ - int inptyp; /* for determining 16 bit or - * 8 bit data. - */ - int vert_starting_pixel; /* for specifying vertical - * starting pixel in input. - */ - int horz_starting_pixel; /* for specyfing horizontal - * starting pixel in input. - */ - int cbilin; /* # defined, filter with luma - * or bi-linear interpolation. - */ - int pix_fmt; /* # defined, UYVY or YUYV */ - int out_hsize; /* output frame horizontal - * size. - */ - int out_vsize; /* output frame vertical - * size. - */ - int out_pitch; /* offset between two rows of - * output frame. - */ - int hstph; /* for specifying horizontal - * starting phase. - */ - int vstph; /* for specifying vertical - * starting phase. - */ - u16 tap4filt_coeffs[32]; /* horizontal filter - * coefficients. - */ - u16 tap7filt_coeffs[32]; /* vertical filter - * coefficients. - */ - struct rsz_yenh yenh_params; -}; - -struct rsz_mult { - int in_hsize; /* input frame horizontal - * size. - */ - int in_vsize; /* input frame vertical size. - */ - int out_hsize; /* output frame horizontal - * size. - */ - int out_vsize; /* output frame vertical - * size. - */ - int in_pitch; /* offset between two rows of - * input frame. - */ - int out_pitch; /* offset between two rows of - * output frame. - */ - int end_hsize; - int end_vsize; - int num_tap; /* 0 = 7tap; 1 = 4tap */ - int active; - int inptyp; - int vrsz; - int hrsz; - int hstph; /* for specifying horizontal - * starting phase. - */ - int vstph; - int pix_fmt; /* # defined, UYVY or YUYV. */ - int cbilin; /* # defined, filter with luma - * or bi-linear. - */ - u16 tap4filt_coeffs[32]; /* horizontal filter - * coefficients. - */ - u16 tap7filt_coeffs[32]; /* vertical filter - * coefficients. - */ -}; - -/* Contains the status of hardware and channel */ -struct rsz_status { - int chan_busy; /* 1: channel is busy, - * 0: channel is not busy - */ - int hw_busy; /* 1: hardware is busy, - * 0: hardware is not busy - */ - int src; /* # defined, can be either - * SD-RAM or CCDC/PREVIEWER - */ -}; - -/* Passed by application for getting crop size */ -struct rsz_cropsize { - unsigned int hcrop; /* Number of pixels per line - * cropped in output image. - */ - - unsigned int vcrop; /* Number of lines cropped - * in output image. - */ -}; - -/* Register mapped structure which contains the every register - information */ -struct resizer_config { - u32 rsz_pcr; /* pcr register mapping - * variable. - */ - u32 rsz_in_start; /* in_start register mapping - * variable. - */ - u32 rsz_in_size; /* in_size register mapping - * variable. - */ - u32 rsz_out_size; /* out_size register mapping - * variable. - */ - u32 rsz_cnt; /* rsz_cnt register mapping - * variable. - */ - u32 rsz_sdr_inadd; /* sdr_inadd register mapping - * variable. - */ - u32 rsz_sdr_inoff; /* sdr_inoff register mapping - * variable. - */ - u32 rsz_sdr_outadd; /* sdr_outadd register mapping - * variable. - */ - u32 rsz_sdr_outoff; /* sdr_outbuff register - * mapping variable. - */ - u32 rsz_coeff_horz[16]; /* horizontal coefficients - * mapping array. - */ - u32 rsz_coeff_vert[16]; /* vertical coefficients - * mapping array. - */ - u32 rsz_yehn; /* yehn(luma)register mapping - * variable. - */ -}; - -/* Channel specific structure contains information regarding - the every channel */ -struct channel_config { - struct resizer_config register_config; /* Instance of register set - * mapping structure - */ - int status; /* Specifies whether the - * channel is busy or not - */ - struct mutex chanprotection_mutex; - enum config_done config_state; - -}; - -/* Global structure which contains information about number of channels - and protection variables */ -struct device_params { - - struct rsz_params *params; - unsigned char opened; /* state of the device */ - struct completion compl_isr; /* Completion for interrupt */ - struct mutex reszwrap_mutex; /* Semaphore for array */ - - struct channel_config *config; /* Pointer to channel - * configuration. - */ - spinlock_t vbq_lock; /* spinlock for videobuf - * queues. - */ - struct videobuf_queue_ops vbq_ops; /* videobuf queue operations */ - dma_addr_t isp_addr_read; /* Input/Output address */ - dma_addr_t isp_addr_write; /* Input/Output address */ -}; - -/* per-filehandle data structure */ -struct rsz_fh { - enum v4l2_buf_type type; - struct videobuf_queue vbq; - struct device_params *device; -}; - -/* functions definition */ -void rsz_hardware_setup(struct channel_config *rsz_conf_chan); -int rsz_set_params(struct rsz_params *, struct channel_config *); -int rsz_get_params(struct rsz_params *, struct channel_config *); -void rsz_copy_data(struct rsz_params *params); -void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2); -void rsz_calculate_crop(struct channel_config *rsz_conf_chan, - struct rsz_cropsize *cropsize); -int rsz_set_multipass(struct channel_config *rsz_conf_chan); -int rsz_set_ratio(struct channel_config *rsz_conf_chan); -void rsz_config_ratio(struct channel_config *rsz_conf_chan); - -#endif Index: omapkernel/include/linux/omap_resizer.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ omapkernel/include/linux/omap_resizer.h 2008-10-14 10:21:13.000000000 -0500 @@ -0,0 +1,136 @@ +/* + * drivers/media/video/isp/omap_resizer.h + * + * Include file for Resizer module wrapper in TI's OMAP3430 ISP + * + * Copyright (C) 2008 Texas Instruments, Inc. + * + * This package 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. + * + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef OMAP_RESIZER_H +#define OMAP_RESIZER_H + +#include <linux/types.h> + +/* ioctls definition */ +#define RSZ_IOC_BASE 'R' +#define RSZ_IOC_MAXNR 8 + +/*Ioctl options which are to be passed while calling the ioctl*/ +#define RSZ_REQBUF _IOWR(RSZ_IOC_BASE, 1,\ + struct v4l2_requestbuffers) +#define RSZ_QUERYBUF _IOWR(RSZ_IOC_BASE, 2, struct v4l2_buffer) +#define RSZ_S_PARAM _IOWR(RSZ_IOC_BASE, 3, struct rsz_params) +#define RSZ_G_PARAM _IOWR(RSZ_IOC_BASE, 4, struct rsz_params) +#define RSZ_RESIZE _IOWR(RSZ_IOC_BASE, 5, __s32) +#define RSZ_G_STATUS _IOWR(RSZ_IOC_BASE, 6, struct rsz_status) +#define RSZ_QUEUEBUF _IOWR(RSZ_IOC_BASE, 7, struct v4l2_buffer) +#define RSZ_GET_CROPSIZE _IOWR(RSZ_IOC_BASE, 8, struct rsz_cropsize) + +#define RSZ_INTYPE_YCBCR422_16BIT 0 +#define RSZ_INTYPE_PLANAR_8BIT 1 +#define RSZ_PIX_FMT_UYVY 1 /* cb:y:cr:y */ +#define RSZ_PIX_FMT_YUYV 0 /* y:cb:y:cr */ + +enum config_done { + STATE_CONFIGURED, /* Resizer driver configured + * by application. + */ + STATE_NOT_CONFIGURED /* Resizer driver not + * configured by application. + */ +}; + +/* Structure Definitions */ + +/* used to luma enhancement options */ + +struct rsz_yenh { + __s32 type; /* represents luma enable or + * disable. + */ + __u8 gain; /* represents gain. */ + __u8 slop; /* represents slop. */ + __u8 core; /* Represents core value. */ +}; + +/* Conatins all the parameters for resizing. This structure + * is used to configure resiser parameters + */ +struct rsz_params { + __s32 in_hsize; /* input frame horizontal + * size. + */ + __s32 in_vsize; /* input frame vertical size */ + __s32 in_pitch; /* offset between two rows of + * input frame. + */ + __s32 inptyp; /* for determining 16 bit or + * 8 bit data. + */ + __s32 vert_starting_pixel; /* for specifying vertical + * starting pixel in input. + */ + __s32 horz_starting_pixel; /* for specyfing horizontal + * starting pixel in input. + */ + __s32 cbilin; /* # defined, filter with luma + * or bi-linear interpolation. + */ + __s32 pix_fmt; /* # defined, UYVY or YUYV */ + __s32 out_hsize; /* output frame horizontal + * size. + */ + __s32 out_vsize; /* output frame vertical + * size. + */ + __s32 out_pitch; /* offset between two rows of + * output frame. + */ + __s32 hstph; /* for specifying horizontal + * starting phase. + */ + __s32 vstph; /* for specifying vertical + * starting phase. + */ + __u16 tap4filt_coeffs[32]; /* horizontal filter + * coefficients. + */ + __u16 tap7filt_coeffs[32]; /* vertical filter + * coefficients. + */ + struct rsz_yenh yenh_params; +}; + +/* Contains the status of hardware and channel */ +struct rsz_status { + __s32 chan_busy; /* 1: channel is busy, + * 0: channel is not busy + */ + __s32 hw_busy; /* 1: hardware is busy, + * 0: hardware is not busy + */ + __s32 src; /* # defined, can be either + * SD-RAM or CCDC/PREVIEWER + */ +}; + +/* Passed by application for getting crop size */ +struct rsz_cropsize { + __u32 hcrop; /* Number of pixels per line + * cropped in output image. + */ + + __u32 vcrop; /* Number of lines cropped + * in output image. + */ +}; + +#endif -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html