/** * ispresizer_busy - Checks if ISP resizer is busy. * * Returns busy field from ISPRSZ_PCR register. **/ int ispresizer_busy(struct isp_res_device *isp_res) { struct device *dev = to_device(isp_res); return isp_reg_readl(dev, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) & ISPRSZ_PCR_BUSY; }
int isph3a_aewb_busy(struct isp_h3a_device *isp_h3a) { struct device *dev = to_device(isp_h3a); return isp_reg_readl(dev, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR) & ISPH3A_PCR_BUSYAEAWB; }
/** * isph3a_aewb_update_regs - Helper function to update h3a registers. **/ void isph3a_aewb_config_registers(struct isp_h3a_device *isp_h3a) { struct device *dev = to_device(isp_h3a); unsigned long irqflags; if (!isp_h3a->aewb_config_local.aewb_enable) return; spin_lock_irqsave(isp_h3a->lock, irqflags); isp_reg_writel(dev, isp_h3a->buf_next->iommu_addr, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST); if (!isp_h3a->update) { spin_unlock_irqrestore(isp_h3a->lock, irqflags); return; } isp_reg_writel(dev, isp_h3a->regs.win1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1); isp_reg_writel(dev, isp_h3a->regs.start, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINSTART); isp_reg_writel(dev, isp_h3a->regs.blk, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK); isp_reg_writel(dev, isp_h3a->regs.subwin, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWSUBWIN); isp_reg_and_or(dev, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR, ~ISPH3A_PCR_AEW_MASK, isp_h3a->regs.pcr); isp_h3a->update = 0; spin_unlock_irqrestore(isp_h3a->lock, irqflags); }
int show_trace_dev_match(char *buf, size_t size) { unsigned int value = hash_value_early_read / (USERHASH * FILEHASH); int ret = 0; struct list_head *entry; /* * It's possible that multiple devices will match the hash and we can't * tell which is the culprit, so it's best to output them all. */ device_pm_lock(); entry = dpm_list.prev; while (size && entry != &dpm_list) { struct device *dev = to_device(entry); unsigned int hash = hash_string(DEVSEED, dev_name(dev), DEVHASH); if (hash == value) { int len = snprintf(buf, size, "%s\n", dev_driver_string(dev)); if (len > size) len = size; buf += len; ret += len; size -= len; } entry = entry->prev; } device_pm_unlock(); return ret; }
/* * This API allows the user to update White Balance gains, as well as * exposure time and analog gain. It is also used to request frame * statistics. */ int isp_af_request_statistics(struct isp_af_device *isp_af, struct isp_af_data *afdata) { struct device *dev = to_device(isp_af); struct ispstat_buffer *buf; if (!isp_af->config.af_config) { dev_dbg(dev, "af: statistics requested while af engine" " is not configured\n"); return -EINVAL; } if (afdata->update & REQUEST_STATISTICS) { buf = ispstat_buf_get(&isp_af->stat, (void *)afdata->af_statistics_buf, afdata->frame_number); if (IS_ERR(buf)) return PTR_ERR(buf); afdata->xtrastats.ts = buf->ts; afdata->config_counter = buf->config_counter; afdata->frame_number = buf->frame_number; ispstat_buf_release(&isp_af->stat); } afdata->curr_frame = isp_af->stat.frame_number; return 0; }
int isp_af_busy(struct isp_af_device *isp_af) { struct device *dev = to_device(isp_af); return isp_reg_readl(dev, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR) & ISPH3A_PCR_BUSYAF; }
/** * ispresizer_set_inaddr - Sets the memory address of the input frame. * @addr: 32bit memory address aligned on 32byte boundary. * @offset: Starting offset. * * Returns 0 if successful, or -EINVAL if address is not 32 bits aligned. **/ int ispresizer_set_inaddr(struct isp_res_device *isp_res, u32 addr, struct isp_node *pipe) { struct device *dev = to_device(isp_res); u32 in_buf_plus_offs = 0; if (addr % 32) return -EINVAL; isp_res->in_buff_addr = addr; if (pipe != NULL) { dev_dbg(dev, "%s: In crop top: %d[%d] left: %d[%d]\n", __func__, isp_res->phy_rect.top, pipe->in.crop.top, isp_res->phy_rect.left, pipe->in.crop.left); /* Calculate additional part to prepare crop offsets */ in_buf_plus_offs = ((isp_res->phy_rect.top * (pipe->in.image.bytesperline / 2) + (isp_res->phy_rect.left & ~0xf)) * ISP_BYTES_PER_PIXEL); /* Set the fractional part of the crop */ ispresizer_set_start(dev, isp_res->phy_rect.left & 0xf, 0); dev_dbg(dev, "%s: In address offs: 0x%08X\n", __func__, in_buf_plus_offs); } isp_reg_writel(dev, isp_res->in_buff_addr + in_buf_plus_offs, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD); dev_dbg(dev, "%s: In address base: 0x%08X\n", __func__, addr); return 0; }
/** * Sets the chrominance algorithm * @cbilin: 0 - chrominance uses same processing as luminance, * 1 - bilinear interpolation processing **/ void ispresizer_enable_cbilin(struct isp_res_device *isp_res, u8 enable) { struct device *dev = to_device(isp_res); isp_reg_and_or(dev, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_CBILIN, (enable ? ISPRSZ_CNT_CBILIN : 0)); }
/** * ispresizer_config_ycpos - Specifies if output should be in YC or CY format. * @yc: 0 - YC format, 1 - CY format **/ void ispresizer_config_ycpos(struct isp_res_device *isp_res, u8 yc) { struct device *dev = to_device(isp_res); isp_reg_and_or(dev, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_YCPOS, (yc ? ISPRSZ_CNT_YCPOS : 0)); }
/** * ispresizer_is_enabled - Checks if ISP resizer is enable. * * Returns busy field from ISPRSZ_PCR register. **/ int ispresizer_is_enabled(struct isp_res_device *isp_res) { struct device *dev = to_device(isp_res); return isp_reg_readl(dev, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) & ISPRSZ_PCR_ENABLE; }
void parse_dpm_list(struct list_head *head, unsigned int idx) { struct list_head *list; struct soc_device *dev; PM_DBG("(%p)", head); list_for_each(list, head) { dev = to_device(list, idx); PM_DBG("-->%s(%p)", dev->name, dev); }
/** * ispresizer_config_size - Configures input and output image size. * @pipe: Resizer data path parameters. * * Configures the appropriate values stored in the isp_res structure in the * resizer registers. * * Returns 0 if successful, or -EINVAL if passed values haven't been verified * with ispresizer_try_size() previously. **/ int ispresizer_s_pipeline(struct isp_res_device *isp_res, struct isp_node *pipe) { struct device *dev = to_device(isp_res); int bpp = ISP_BYTES_PER_PIXEL; ispresizer_set_source(isp_res, pipe->in.path); ispresizer_set_intype(isp_res, pipe->in.path); ispresizer_set_start_phase(dev, NULL); ispresizer_set_luma_enhance(dev, NULL); if (pipe->in.image.pixelformat == V4L2_PIX_FMT_YUYV) ispresizer_config_ycpos(isp_res, 1); else ispresizer_config_ycpos(isp_res, 0); ispresizer_try_pipeline(isp_res, pipe); ispresizer_set_ratio(dev, isp_res->h_resz, isp_res->v_resz); ispresizer_set_coeffs(dev, NULL, isp_res->h_resz, isp_res->v_resz); /* Switch filter, releated to up/down scale */ if (ispresizer_is_upscale(pipe)) ispresizer_enable_cbilin(isp_res, 1); else ispresizer_enable_cbilin(isp_res, 0); /* Set input and output size */ ispresizer_set_input_size(dev, isp_res->phy_rect.width, isp_res->phy_rect.height); ispresizer_set_output_size(dev, pipe->out.image.width, pipe->out.image.height); /* Set input address and line offset address */ if (pipe->in.path != RSZ_OTFLY_YUV) { /* Set the input address, plus calculated crop offset */ ispresizer_set_inaddr(isp_res, isp_res->in_buff_addr, pipe); /* Set the input line offset/length */ ispresizer_set_in_offset(isp_res, pipe->in.image.bytesperline); } else { /* Set the input address.*/ ispresizer_set_inaddr(isp_res, 0, NULL); /* Set the starting pixel offset */ ispresizer_set_start(dev, isp_res->phy_rect.left * bpp, isp_res->phy_rect.top); ispresizer_set_in_offset(isp_res, 0); } /* Set output line offset */ ispresizer_set_out_offset(isp_res, pipe->out.image.bytesperline); return 0; }
/** * ispresizer_try_size - Validates input and output images size. * @pipe: Resizer data path parameters. * * Calculates the horizontal and vertical resize ratio, number of pixels to * be cropped in the resizer module and checks the validity of various * parameters. Formula used for calculation is:- * * 8-phase 4-tap mode :- * inputwidth = (32 * sph + (ow - 1) * hrsz + 16) >> 8 + 7 * inputheight = (32 * spv + (oh - 1) * vrsz + 16) >> 8 + 4 * endpahse for width = ((32 * sph + (ow - 1) * hrsz + 16) >> 5) % 8 * endphase for height = ((32 * sph + (oh - 1) * hrsz + 16) >> 5) % 8 * * 4-phase 7-tap mode :- * inputwidth = (64 * sph + (ow - 1) * hrsz + 32) >> 8 + 7 * inputheight = (64 * spv + (oh - 1) * vrsz + 32) >> 8 + 7 * endpahse for width = ((64 * sph + (ow - 1) * hrsz + 32) >> 6) % 4 * endphase for height = ((64 * sph + (oh - 1) * hrsz + 32) >> 6) % 4 * */ int ispresizer_try_pipeline(struct isp_res_device *isp_res, struct isp_node *pipe) { /*+++++20111007, Jimmy Su add, TI FIFO_UNDERFLOW patch*/ u8 bpp; if (pipe->in.image.pixelformat == V4L2_PIX_FMT_YUYV || pipe->in.image.pixelformat == V4L2_PIX_FMT_UYVY) { pipe->in.image.colorspace = V4L2_COLORSPACE_JPEG; } else { pipe->in.image.colorspace = V4L2_COLORSPACE_SRGB; } if (pipe->in.path == RSZ_MEM_COL8) { bpp=1; } else { bpp=2; } // u16 extraBpp = (pipe->in.image.width * bpp) % PHY_ADDRESS_ALIGN; // // if ( extraBpp != 0){ // pipe->in.crop.left = extraBpp / bpp; // pipe->in.image.width -= extraBpp / bpp; // if (isp_res != NULL) // isp_res->phy_rect.left = pipe->in.crop.left; // } if (ispresizer_try_fmt(pipe, pipe->in.path != RSZ_OTFLY_YUV)) return -EINVAL; if (ispresizer_try_ratio(to_device(isp_res), pipe, &isp_res->phy_rect, &isp_res->h_resz, &isp_res->v_resz)) return -EINVAL; pipe->in.image.bytesperline = ALIGN((pipe->in.image.width * bpp), PHY_ADDRESS_ALIGN); pipe->in.image.field = V4L2_FIELD_NONE; pipe->in.image.sizeimage = pipe->in.image.bytesperline * pipe->in.image.height; pipe->out.image.bytesperline = ALIGN(pipe->out.image.width * bpp, PHY_ADDRESS_ALIGN); pipe->out.image.field = pipe->in.image.field; pipe->out.image.colorspace = pipe->in.image.colorspace; pipe->out.image.pixelformat = pipe->in.image.pixelformat; pipe->out.image.sizeimage = pipe->out.image.bytesperline * pipe->out.image.height; /*-----20111007, Jimmy Su add, TI FIFO_UNDERFLOW patch*/ return 0; }
/** * ispresizer_set_out_offset - Configures the write address line offset. * @offset: Line offset for the preview output. * * Returns 0 if successful, or -EINVAL if address is not 32 bits aligned. **/ int ispresizer_set_out_offset(struct isp_res_device *isp_res, u32 offset) { struct device *dev = to_device(isp_res); if (offset % 32) return -EINVAL; isp_reg_writel(dev, offset << ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF); dev_dbg(dev, "%s: Out offset: 0x%04X\n", __func__, offset); return 0; }
/** * Configures the memory address to which the output frame is written. * @addr: 32bit memory address aligned on 32byte boundary. **/ int ispresizer_set_outaddr(struct isp_res_device *isp_res, u32 addr) { struct device *dev = to_device(isp_res); if (addr % 32) return -EINVAL; isp_reg_writel(dev, addr << ISPRSZ_SDR_OUTADD_ADDR_SHIFT, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD); dev_dbg(dev, "%s: Out address: 0x%08X\n", __func__, addr); return 0; }
void dpm_power_up(void) { while(!list_empty(&dpm_off_irq)) { struct list_head * entry = dpm_off_irq.next; struct device * dev = to_device(entry); get_device(dev); list_del_init(entry); list_add_tail(entry, &dpm_active); resume_device(dev); put_device(dev); } }
void isp_af_isr(struct isp_af_device *af) { isp_af_enable(af, 0); /* If it's busy we can't process this buffer anymore */ if (!isp_af_busy(af)) { isp_af_buf_process(af); isp_af_config_registers(af); } else { dev_dbg(to_device(af), "af: cannot process buffer, device is busy.\n"); } isp_af_enable(af, 1); }
/** * ispresizer_set_intype - Input type select * @isp_res: Device context. * @type: Pixel format type. */ static inline void ispresizer_set_intype(struct isp_res_device *isp_res, enum resizer_input type) { struct device *dev = to_device(isp_res); if (type == RSZ_MEM_COL8) isp_reg_or(dev, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ISPRSZ_CNT_INPTYP); else isp_reg_and(dev, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_INPTYP); dev_dbg(dev, "%s: In type: %u\n", __func__, type); }
/** * ispresizer_set_source - Input source select * @isp_res: Device context. * @source: Input source type * * If this field is set to RSZ_OTFLY_YUV, the resizer input is fed from * Preview/CCDC engine, otherwise from memory. */ static inline void ispresizer_set_source(struct isp_res_device *isp_res, enum resizer_input source) { struct device *dev = to_device(isp_res); if (source != RSZ_OTFLY_YUV) isp_reg_or(dev, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ISPRSZ_CNT_INPSRC); else isp_reg_and(dev, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_INPSRC); dev_dbg(dev, "%s: In source: %u\n", __func__, source); }
/** * isph3a_aewb_request_statistics - REquest statistics and update gains in AEWB * @aewbdata: Pointer to return AE AWB statistics data. * * This API allows the user to update White Balance gains, as well as * exposure time and analog gain. It is also used to request frame * statistics. * * Returns 0 if successful, -EINVAL when H3A engine is not enabled, or other * errors when setting gains. **/ int isph3a_aewb_request_statistics(struct isp_h3a_device *isp_h3a, struct isph3a_aewb_data *aewbdata) { struct device *dev = to_device(isp_h3a); unsigned long irqflags; int ret = 0; if (!isp_h3a->aewb_config_local.aewb_enable) { dev_dbg(dev, "h3a: engine not enabled\n"); return -EINVAL; } DPRINTK_ISPH3A("isph3a_aewb_request_statistics: Enter " "(frame req. => %d, current frame => %d," "update => %d)\n", aewbdata->frame_number, isp_h3a->stat.frame_number, aewbdata->update); DPRINTK_ISPH3A("User data received: \n"); DPRINTK_ISPH3A("Digital gain = 0x%04x\n", aewbdata->dgain); DPRINTK_ISPH3A("WB gain b *= 0x%04x\n", aewbdata->wb_gain_b); DPRINTK_ISPH3A("WB gain r *= 0x%04x\n", aewbdata->wb_gain_r); DPRINTK_ISPH3A("WB gain gb = 0x%04x\n", aewbdata->wb_gain_gb); DPRINTK_ISPH3A("WB gain gr = 0x%04x\n", aewbdata->wb_gain_gr); spin_lock_irqsave(isp_h3a->lock, irqflags); if (aewbdata->update & SET_DIGITAL_GAIN) isp_h3a->h3awb_update.dgain = (u16)aewbdata->dgain; if (aewbdata->update & SET_COLOR_GAINS) { isp_h3a->h3awb_update.coef0 = (u8)aewbdata->wb_gain_r; isp_h3a->h3awb_update.coef1 = (u8)aewbdata->wb_gain_gr; isp_h3a->h3awb_update.coef2 = (u8)aewbdata->wb_gain_gb; isp_h3a->h3awb_update.coef3 = (u8)aewbdata->wb_gain_b; } if (aewbdata->update & (SET_COLOR_GAINS | SET_DIGITAL_GAIN)) isp_h3a->wb_update = 1; spin_unlock_irqrestore(isp_h3a->lock, irqflags); if (aewbdata->update & REQUEST_STATISTICS) ret = isph3a_aewb_get_stats(isp_h3a, aewbdata); aewbdata->curr_frame = isp_h3a->stat.frame_number; DPRINTK_ISPH3A("isph3a_aewb_request_statistics: " "aewbdata->h3a_aewb_statistics_buf => %p\n", aewbdata->h3a_aewb_statistics_buf); return ret; }
static ssize_t pwrscale_sysfs_show(struct kobject *kobj, struct attribute *attr, char *buf) { struct kgsl_device *device = to_device(kobj); struct kgsl_pwrscale_attribute *pattr = to_pwrscale_attr(attr); ssize_t ret; if (pattr->show) ret = pattr->show(device, buf); else ret = -EIO; return ret; }
static void __isp_af_enable(struct isp_af_device *isp_af, int enable) { struct device *dev = to_device(isp_af); unsigned int pcr; pcr = isp_reg_readl(dev, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR); /* Set AF_EN bit in PCR Register */ if (enable) pcr |= AF_EN; else pcr &= ~AF_EN; isp_reg_writel(dev, pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR); }
static ssize_t pwrscale_sysfs_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) { struct kgsl_device *device = to_device(kobj); struct kgsl_pwrscale_attribute *pattr = to_pwrscale_attr(attr); ssize_t ret; if (pattr->store) ret = pattr->store(device, buf, count); else ret = -EIO; return ret; }
static int show_dev_hash(unsigned int value) { int match = 0; struct list_head *entry = dpm_list.prev; while (entry != &dpm_list) { struct device * dev = to_device(entry); unsigned int hash = hash_string(DEVSEED, dev_name(dev), DEVHASH); if (hash == value) { dev_info(dev, "hash matches\n"); match++; } entry = entry->prev; } return match; }
static int show_dev_hash(unsigned int value) { int match = 0; struct list_head * entry = dpm_active.prev; while (entry != &dpm_active) { struct device * dev = to_device(entry); unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH); if (hash == value) { printk(" hash matches device %s\n", dev->bus_id); match++; } entry = entry->prev; } return match; }
/** * ispresizer_free - Makes Resizer module free. * * Returns 0 if successful, or -EINVAL if resizer module was already freed. **/ int ispresizer_free(struct isp_res_device *isp_res) { struct device *dev = to_device(isp_res); mutex_lock(&isp_res->ispres_mutex); if (isp_res->res_inuse) { isp_res->res_inuse = 0; mutex_unlock(&isp_res->ispres_mutex); isp_reg_and(dev, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ~(ISPCTRL_RSZ_CLK_EN | ISPCTRL_SBL_WR0_RAM_EN)); return 0; } else { mutex_unlock(&isp_res->ispres_mutex); dev_err(dev, "Resizer Module already freed\n"); return -EINVAL; } }
void __isph3a_aewb_enable(struct isp_h3a_device *isp_h3a, u8 enable) { struct device *dev = to_device(isp_h3a); u32 pcr = isp_reg_readl(dev, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR); if (enable) { #ifdef CONFIG_VIDEO_OMAP34XX_ISP_DEBUG_FS struct isp_device *isp = to_isp_device(isp_h3a); if (isp->dfs_h3a) isph3a_dfs_dump(isp); #endif pcr |= ISPH3A_PCR_AEW_EN; } else { pcr &= ~ISPH3A_PCR_AEW_EN; } isp_reg_writel(dev, pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR); }
void dpm_resume(void) { down(&dpm_list_sem); while(!list_empty(&dpm_off)) { struct list_head * entry = dpm_off.next; struct device * dev = to_device(entry); get_device(dev); list_del_init(entry); list_add_tail(entry, &dpm_active); up(&dpm_list_sem); if (!dev->power.prev_state.event) resume_device(dev); down(&dpm_list_sem); put_device(dev); } up(&dpm_list_sem); }
/** * ispresizer_request - Reserves the Resizer module. * * Allows only one user at a time. * * Returns 0 if successful, or -EBUSY if resizer module was already requested. **/ int ispresizer_request(struct isp_res_device *isp_res) { struct device *dev = to_device(isp_res); mutex_lock(&isp_res->ispres_mutex); if (!isp_res->res_inuse) { isp_res->res_inuse = 1; mutex_unlock(&isp_res->ispres_mutex); isp_reg_writel(dev, isp_reg_readl(dev, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL) | ISPCTRL_SBL_WR0_RAM_EN | ISPCTRL_RSZ_CLK_EN, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL); return 0; } else { mutex_unlock(&isp_res->ispres_mutex); dev_err(dev, "resizer: Module Busy\n"); return -EBUSY; } }
/** * ispresizer_enable - Enables the resizer module. * @enable: 1 - Enable, 0 - Disable * * Client should configure all the sub modules in resizer before this. **/ void ispresizer_enable(struct isp_res_device *isp_res, int enable) { struct device *dev = to_device(isp_res); int val; if (enable) { #ifdef CONFIG_VIDEO_OMAP34XX_ISP_DEBUG_FS struct isp_device *isp = to_isp_device(isp_res); if (isp->dfs_resz) ispresz_dfs_dump(isp); #endif val = (isp_reg_readl(dev, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) & ISPRSZ_PCR_ONESHOT) | ISPRSZ_PCR_ENABLE; } else { val = isp_reg_readl(dev, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) & ~ISPRSZ_PCR_ENABLE; } isp_reg_writel(dev, val, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR); }