/** * Set output hue * * @lw_par: logiWIN data * @hue: output hue in range (-30,30) * */ void logiwin_set_hue(struct logiwin_parameters *lw_par, int hue) { static const unsigned int cos_table[31] = { 2048, 2047, 2046, 2045, 2043, 2040, 2036, 2032, 2028, 2022, 2016, 2010, 2003, 1995, 1987, 1978, 1968, 1958, 1947, 1936, 1924, 1911, 1898, 1885, 1870, 1856, 1840, 1824, 1808, 1791, 1773 }; static const unsigned int sin_table[31] = { 0, 35, 71, 107, 142, 178, 214, 249, 285, 320, 355, 390, 425, 460, 495, 530, 564, 598, 632, 666, 700, 733, 767, 800, 832, 865, 897, 929, 961, 992, 1024 }; u32 reg_cos, reg_sin; if (hue < -30) hue = -30; else if (hue > 30) hue = 30; lw_par->hue = hue; reg_cos = (hue < 0) ? cos_table[-hue] : cos_table[hue]; reg_sin = (hue < 0) ? -sin_table[-hue] : sin_table[hue]; logiwin_write32(lw_par, LOGIWIN_COS_HUE_ROFF, reg_cos); logiwin_write32(lw_par, LOGIWIN_SIN_HUE_ROFF, reg_sin); }
/** * Enable/disable logiWIN deinterlacing * * @lw_par: logiWIN data * @enable: enable/disable flag * * Note: * false: "Bob" * true: "Weave" * */ void logiwin_weave_deinterlace(struct logiwin_parameters *lw_par, bool weave_deinterlace) { if (lw_par->input_format != LOGIWIN_FORMAT_INPUT_ITU) return; if (weave_deinterlace) { lw_par->ctrl |= LOGIWIN_CTRL_WEAVE_DEINTERLACE; lw_par->out.top /= 2; lw_par->out.height /= 2; lw_par->vscale_step *= 2; } else { lw_par->ctrl &= ~LOGIWIN_CTRL_WEAVE_DEINTERLACE; lw_par->out.top *= 2; lw_par->out.height *= 2; lw_par->vscale_step = (lw_par->vscale_step / 2) & ((~0) << lw_par->scale_shift); } lw_par->weave_deinterlace = weave_deinterlace; if (lw_par->ctrl & LOGIWIN_CTRL_ENABLE) { lw_par->ctrl &= ~LOGIWIN_CTRL_ENABLE; logiwin_write32(lw_par, LOGIWIN_CTRL0_ROFF, lw_par->ctrl); udelay(10); lw_par->ctrl |= LOGIWIN_CTRL_ENABLE; } logiwin_write32(lw_par, LOGIWIN_CTRL0_ROFF, lw_par->ctrl); }
/** * * Switch H sync and V sync polarity * * @lw_par: logiWIN data * @ch: input channel * @hsync_inv: switch H sync polarity * @vsync_inv: switch V sync polarity * */ void logiwin_sync_polarity(struct logiwin_parameters *lw_par, unsigned int ch, bool hsync_inv, bool vsync_inv) { if (ch > 1) return; if (ch == 0) { if (hsync_inv) lw_par->ctrl |= LOGIWIN_HSYNC_INVERT_CH_0; else lw_par->ctrl &= ~LOGIWIN_HSYNC_INVERT_CH_0; if (vsync_inv) lw_par->ctrl |= LOGIWIN_VSYNC_INVERT_CH_0; else lw_par->ctrl &= ~LOGIWIN_VSYNC_INVERT_CH_0; } else if (ch == 1) { if (hsync_inv) lw_par->ctrl |= LOGIWIN_HSYNC_INVERT_CH_1; else lw_par->ctrl &= ~LOGIWIN_HSYNC_INVERT_CH_1; if (vsync_inv) lw_par->ctrl |= LOGIWIN_VSYNC_INVERT_CH_1; else lw_par->ctrl &= ~LOGIWIN_VSYNC_INVERT_CH_1; } logiwin_write32(lw_par, LOGIWIN_CTRL0_ROFF, lw_par->ctrl); }
/** * * Enables or disables logiWIN deinterlacing operation. * * @param lw is a pointer to the logiWIN device parameter structure. * @param weave_deinterlace is a flag for enabling "weave" deinterlace. * * @return None. * * @note * - 0 - "Bob" deinterlace. * - 1 - "Weave" deinterlace. * *****************************************************************************/ void logiwin_enable_weave_deinterlace(struct logiwin_priv *lw, unsigned char weave_deinterlace) { if (lw->input_format != LOGIWIN_ITU) return; if (!lw->weave_deinterlace == !weave_deinterlace) return; if (weave_deinterlace) { lw->ctrl |= LOGIWIN_CR_WEAVE_DEINT_MSK; lw->out_rect.y /= 2; lw->out_rect.height /= 2; lw->scale_step_y *= 2; } else { lw->ctrl &= (~LOGIWIN_CR_WEAVE_DEINT_MSK); lw->out_rect.y *= 2; lw->out_rect.height *= 2; lw->scale_step_y = (lw->scale_step_y / 2) & ((~0) << lw->scale_shift_bits); } lw->weave_deinterlace = weave_deinterlace; logiwin_write32(lw->reg_base, LOGIWIN_CTRL0_ROFF, lw->ctrl); }
/** * Enable/disable logiWIN operation * * @lw_par: logiWIN data * @op: logiWIN operation * @op_flag: logiWIN operation flag * */ void logiwin_operation(struct logiwin_parameters *lw_par, enum logiwin_operation op, enum logiwin_operation_flag op_flag) { u32 op_mask; unsigned int us = 0; switch (op) { case LOGIWIN_OP_ENABLE: op_mask = LOGIWIN_CTRL_ENABLE; break; case LOGIWIN_OP_EVEN_FIELD_VBUFF_SWITCH: op_mask = LOGIWIN_CTRL_EVEN_FIELD_VBUFF_SWITCH; break; case LOGIWIN_OP_STENCIL_MASK: op_mask = LOGIWIN_CTRL_STENCIL_MASK; break; case LOGIWIN_OP_CPU_VBUFF_SWITCH: op_mask = LOGIWIN_CTRL_CPU_VBUFF_SWITCH; break; case LOGIWIN_OP_FRAME_STORED_STOP: op_mask = LOGIWIN_CTRL_FRAME_STORE_STOP; us = 10; break; case LOGIWIN_OP_SWIZZLE: op_mask = LOGIWIN_CTRL_SWIZZLE; us = 10; break; } if (op_flag == LOGIWIN_OP_FLAG_ENABLE) lw_par->ctrl |= op_mask; else if (op_flag == LOGIWIN_OP_FLAG_DISABLE) lw_par->ctrl &= ~op_mask; if (us != 0 && (lw_par->ctrl & LOGIWIN_CTRL_ENABLE)) { lw_par->ctrl &= ~LOGIWIN_CTRL_ENABLE; logiwin_write32(lw_par, LOGIWIN_CTRL0_ROFF, lw_par->ctrl); udelay(us); lw_par->ctrl |= LOGIWIN_CTRL_ENABLE; } logiwin_write32(lw_par, LOGIWIN_CTRL0_ROFF, lw_par->ctrl); }
/** * * Input Video Channel Selection. * * @param lw is a pointer to the logiWIN device parameter structure. * @param select is a flag for choosing between two video input streams. * * @return None. * * @note 0 - logiWIN input channel 0 selected.\n * 1 - logiWIN input channel 1 selected. * *****************************************************************************/ void logiwin_select_input_ch(struct logiwin_priv *lw, unsigned char select) { if (select == 1) lw->ctrl |= LOGIWIN_CR_IN_CH_SEL_MSK; else lw->ctrl &= (~LOGIWIN_CR_IN_CH_SEL_MSK); logiwin_write32(lw->reg_base, LOGIWIN_CTRL0_ROFF, lw->ctrl); }
/** * Enable/disable logiWIN interrupt * * @lw_par: logiWIN data * @mask: interrupt bit mask * */ void logiwin_int(struct logiwin_parameters *lw_par, u32 mask, bool enable) { if (enable) lw_par->int_mask &= ~mask; else lw_par->int_mask |= mask; logiwin_write32(lw_par, LOGIWIN_INT_MASK_ROFF, lw_par->int_mask); }
/** * * Enables/disables logiWIN output image masking operation. * * @param lw is a pointer to the logiWIN device parameter structure. * @param enable is an enable/disable flag. * * @return None. * * @note None. * *****************************************************************************/ void logiwin_enable_image_masking(struct logiwin_priv *lw, unsigned char enable) { if (enable) lw->ctrl |= LOGIWIN_CR_MASK_ENABLE_MSK; else lw->ctrl &= (~LOGIWIN_CR_MASK_ENABLE_MSK); logiwin_write32(lw->reg_base, LOGIWIN_CTRL0_ROFF, lw->ctrl); }
/** * * This function is valid only when logiWIN input is configured for * ITU(interlaced) video stream with double buffering in use. * It enables video buffer switching after both fields are stored to memory * i.e. on every even field. * * @param lw is a pointer to the logiWIN device parameter structure. * @param enable is a flag for enabling switching video buffer on every * even field. * * @return None. * * @note None. * *****************************************************************************/ void logiwin_logiwin_enable_buff_sw_even_field(struct logiwin_priv *lw, unsigned char enable) { if (enable) lw->ctrl |= LOGIWIN_CR_SWBUFF_EVEN_FLD_MSK; else lw->ctrl &= (~LOGIWIN_CR_SWBUFF_EVEN_FLD_MSK); logiwin_write32(lw->reg_base, LOGIWIN_CTRL0_ROFF, lw->ctrl); }
/** * Clears logiWIN interrupt status register * * @lw_par: logiWIN data * @mask: interrupt bit mask * */ void logiwin_int_stat_clear(struct logiwin_parameters *lw_par, u32 mask) { u32 isr; if (mask) isr = mask; else isr = ~mask; logiwin_write32(lw_par, LOGIWIN_INT_STAT_ROFF, isr); }
/** * Input video channel selection * * @lw_par: logiWIN data * @ch: channel ID (0, 1) * */ void logiwin_select_input_ch(struct logiwin_parameters *lw_par, unsigned int ch) { if (ch == 0) lw_par->ctrl &= ~LOGIWIN_CTRL_INPUT_SELECT; else if (ch == 1) lw_par->ctrl |= LOGIWIN_CTRL_INPUT_SELECT; else return; lw_par->channel_id = ch; logiwin_write32(lw_par, LOGIWIN_CTRL0_ROFF, lw_par->ctrl); }
/** * Set output contrast * * @lw_par: logiWIN data * @contrast: output contrast in range (-50,50) * */ void logiwin_set_contrast(struct logiwin_parameters *lw_par, int contrast) { u32 regval; if (contrast < -50) contrast = -50; else if (contrast > 50) contrast = 50; lw_par->contrast = contrast; regval = 1992 * (contrast + 50) * 2048 / 100000; logiwin_write32(lw_par, LOGIWIN_CONTRAST_ROFF, regval); }
/** * Set output brightness * * @lw_par: logiWIN data * @brightness: output brightness in range (-50,50) * */ void logiwin_set_brightness(struct logiwin_parameters *lw_par, int brightness) { u32 regval; if (brightness < -50) brightness = -50; else if (brightness > 50) brightness = 50; lw_par->brightness = brightness; regval = 32 + ((63 * brightness) / 100); logiwin_write32(lw_par, LOGIWIN_BRIGHTNESS_ROFF, regval); }
/** * Write mask stencil to dedicated BRAM registers * * @lw_par: logiWIN data * @mask_buffer: input mask data * @offset: mask offset * @length: input mask data length * * Note: * Offset and length must be even values. * */ void logiwin_write_mask_stencil(struct logiwin_parameters *lw_par, unsigned int *mask_buffer, unsigned int offset, unsigned int length) { unsigned int pos, end, *buff; if ((offset >= MAX_VMEM_STRIDE) || (offset + length > MAX_VMEM_STRIDE)) return; pos = LOGIWIN_MASK_BRAM_OFFSET + offset * 2; end = pos + length * 2; buff = mask_buffer; for (; pos < end; pos += 4, buff++) logiwin_write32(lw_par, pos, *buff); }
/** * Set output saturation * * @lw_par: logiWIN data * @saturation: output saturation in range (-50,50) * */ void logiwin_set_saturation(struct logiwin_parameters *lw_par, int saturation) { u32 regval; if (saturation < -50) saturation = -50; else if (saturation > 50) saturation = 50; lw_par->saturation = saturation; regval = 1992 * (saturation + 50) * 2048 / 100000; logiwin_write32(lw_par, LOGIWIN_SATURATION_ROFF, regval); }
/** * Set logiWIN frame rate * * @lw_par: logiWIN data * @frame_rate: frame rate * * Note: * Frame rate smaller than full instructs logiWIN to store 75%, 50% or 25% * of total frames per second. * */ void logiwin_set_frame_rate(struct logiwin_parameters *lw_par, enum logiwin_frame_rate frame_rate) { lw_par->ctrl &= LOGIWIN_FRAME_RATE_MASK_FULL; switch(frame_rate) { case LOGIWIN_FRAME_RATE_75: lw_par->ctrl |= LOGIWIN_FRAME_RATE_MASK_75; break; case LOGIWIN_FRAME_RATE_50: lw_par->ctrl |= LOGIWIN_FRAME_RATE_MASK_50; break; case LOGIWIN_FRAME_RATE_25: lw_par->ctrl |= LOGIWIN_FRAME_RATE_MASK_25; break; case LOGIWIN_FRAME_RATE_FULL: default: break; } logiwin_write32(lw_par, LOGIWIN_CTRL0_ROFF, lw_par->ctrl); }
/** * * Sets logiWIN frame rate. * * @param lw is a pointer to the logiWIN device parameter structure. * @param frame_rate_sel is a frame rate selector. * * @return None. * * @note * frame_rate_sel : * - FRAME_RATE_FULL - full frame rate * - FRAME_RATE_75 - 75% frame is stored * - FRAME_RATE_50 - 50% frame is stored * - FRAME_RATE_25 - 25% frame is stored * *****************************************************************************/ void logiwin_set_frame_rate(struct logiwin_priv *lw, enum logiwin_frame_rate frame_rate_sel) { lw->ctrl &= 0x3F; switch(frame_rate_sel) { case FRAME_RATE_FULL: lw->ctrl |= LOGIWIN_CR_FULL_FR_MSK; break; case FRAME_RATE_75: lw->ctrl |= LOGIWIN_CR_75_FR_MSK; break; case FRAME_RATE_50: lw->ctrl |= LOGIWIN_CR_50_FR_MSK; break; case FRAME_RATE_25: lw->ctrl |= LOGIWIN_CR_25_FR_MSK; break; } logiwin_write32(lw->reg_base, LOGIWIN_CTRL0_ROFF, lw->ctrl); }
/** * Update logiWIN registers * * @lw_par: logiWIN data * */ void logiwin_update_registers(struct logiwin_parameters *lw_par) { logiwin_write32(lw_par, LOGIWIN_DR_X_ROFF, lw_par->output.dr_x - 1); logiwin_write32(lw_par, LOGIWIN_DR_Y_ROFF, lw_par->output.dr_y - 1); logiwin_write32(lw_par, LOGIWIN_UL_X_ROFF, lw_par->output.ul_x); logiwin_write32(lw_par, LOGIWIN_UL_Y_ROFF, lw_par->output.ul_y); logiwin_write32(lw_par, LOGIWIN_SCALE_X_ROFF, (lw_par->hscale_step >> lw_par->scale_shift)); logiwin_write32(lw_par, LOGIWIN_SCALE_Y_ROFF, (lw_par->vscale_step >> lw_par->scale_shift)); logiwin_write32(lw_par, LOGIWIN_START_X_ROFF, (lw_par->start_x >> lw_par->scale_shift)); logiwin_write32(lw_par, LOGIWIN_START_Y_ROFF, (lw_par->start_y >> lw_par->scale_shift)); logiwin_write32(lw_par, LOGIWIN_CROP_X_ROFF, lw_par->crop.left); logiwin_write32(lw_par, LOGIWIN_CROP_Y_ROFF, lw_par->crop.top); }
/** * * Disable interrupt in logiWIN interrupt mask register. * * @param lw is a pointer to the logiWIN device parameter structure. * @param mask is a interrupt bit mask. * * @return None. * * @note None. * *****************************************************************************/ void logiwin_mask_int(struct logiwin_priv *lw, unsigned long mask) { lw->int_mask |= mask; logiwin_write32(lw->reg_base, LOGIWIN_INT_MASK_ROFF, lw->int_mask); }
/** * * Sets logiWIN memory offset values. * * @param lw is a pointer to the logiWIN device parameter structure. * @param even_ptr is a memory pointer for the even field of the processed * Video input stream. * @param odd_ptr is a memory pointer for the odd field of the processed Video * input stream. * * @return None. * * @note \n For VGA video input or ITU656 in "bob" deinterlace mode only * even_ptr is used. * \n odd_ptr is used only when logiWIN has ITU656 as video input and * is working in "weave" deinterlace mode. * \n even_ptr defines pointer to the block of video memory where even * field are stored. * \n odd_ptr defines pointer to the block of video memory where odd * field are stored. * *****************************************************************************/ void logiwin_set_memory_offset(struct logiwin_priv *lw, unsigned long even_ptr, unsigned long odd_ptr) { logiwin_write32(lw->reg_base, LOGIWIN_MEM_OFFSET_EVEN_ROFF, even_ptr); logiwin_write32(lw->reg_base, LOGIWIN_MEM_OFFSET_ODD_ROFF, odd_ptr); }
/** * * Stops logiWIN operation. * * @param lw is a pointer to the logiWIN device parameter structure. * * @return None. * * @note None. * *****************************************************************************/ void logiwin_stop(struct logiwin_priv *lw) { lw->ctrl &= ~(LOGIWIN_CR_ENABLE_MSK); logiwin_write32(lw->reg_base, LOGIWIN_CTRL0_ROFF, lw->ctrl); }
/** * Set logiWIN memory offsets * * @lw_par: logiWIN data * @even_ptr: memory pointer to even field of the video input stream * @odd_ptr: memory pointer to odd field of the video input stream * * Note: * For VGA or ITU656 in "bob" deinterlace mode video inputs, only even_ptr * is used. * For ITU656 video input in "weave" deinterlace mode, additionally odd_ptr * is used. * even_ptr defines pointer to the block of video memory where even fields * are stored. * odd_ptr defines pointer to the block of video memory where odd fields * are stored. * */ void logiwin_set_memory_offset(struct logiwin_parameters *lw_par, u32 even_ptr, u32 odd_ptr) { logiwin_write32(lw_par, LOGIWIN_MEM_OFFSET_EVEN_ROFF, even_ptr); logiwin_write32(lw_par, LOGIWIN_MEM_OFFSET_ODD_ROFF, odd_ptr); }
/** * Set logiWIN pixel alpha blending value * * @lw_par: logiWIN data * @alpha: pixel alpha value * */ void logiwin_set_pixel_alpha(struct logiwin_parameters *lw_par, u32 alpha) { lw_par->alpha = (u8)alpha; logiwin_write32(lw_par, LOGIWIN_PIX_ALPHA_ROFF, alpha); }
/** * * Clears logiWIN interrupt status register. * * @param lw is a pointer to the logiWIN device parameter structure. * @param mask is a interrupt bit mask. * * @return None. * * @note None. * *****************************************************************************/ void logiwin_clear_int_stat(struct logiwin_priv *lw, unsigned long mask) { logiwin_write32(lw->reg_base, LOGIWIN_INT_STAT_ROFF, mask); }