void lcd_init_device(void) { semaphore_init(&g_wait_sema, 1, 0); /* I'm not really sure this pin is related to power, it does not seem to do anything */ imx233_pinctrl_acquire(1, 8, "lcd_power"); imx233_pinctrl_acquire(1, 9, "lcd_spi_sdo"); imx233_pinctrl_acquire(1, 10, "lcd_spi_scl"); imx233_pinctrl_acquire(1, 11, "lcd_spi_cs"); imx233_pinctrl_set_function(1, 9, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_set_function(1, 10, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_set_function(1, 11, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_set_function(1, 8, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_enable_gpio(1, 8, true); /** lcd is 320x240, data bus is 8-bit, depth is 24-bit so we need 3clk/pix * by running PIX clock at 24MHz we can sustain ~100 fps */ imx233_clkctrl_enable(CLK_PIX, false); imx233_clkctrl_set_div(CLK_PIX, 2); imx233_clkctrl_set_bypass(CLK_PIX, true); /* use XTAL */ imx233_clkctrl_enable(CLK_PIX, true); imx233_lcdif_init(); imx233_lcdif_setup_dotclk_pins(8, false); imx233_lcdif_set_word_length(8); imx233_lcdif_set_underflow_cb(&lcd_underflow); imx233_lcdif_enable_underflow_irq(true); imx233_dma_clkgate_channel(APB_LCDIF, true); imx233_dma_reset_channel(APB_LCDIF); /** Datasheet states: * 257H >= VBP >= 3H, VBP > VLW, VFP >= 1H * 1533clk >= HBP >= 24clk, HBP > HLW, HFP >= 4clk * * Take VLW=1H, VBP=3H, VFP=1H, HLW=8, HBP=24, HFP=4 * Take 3clk/pix because we send 24-bit/pix with 8-bit data bus * Keep consistent with register setting in lcd_init_seq */ imx233_lcdif_setup_dotclk_ex(/*v_pulse_width*/1, /*v_back_porch*/3, /*v_front_porch*/1, /*h_pulse_width*/8, /*h_back_porch*/24, /*h_front_porch*/4, LCD_WIDTH, LCD_HEIGHT, /*clk_per_pix*/3, /*enable_present*/false); imx233_lcdif_set_byte_packing_format(0xf); imx233_lcdif_enable_sync_signals(true); // we need frame signals during init // setup dma unsigned size = IMX233_FRAMEBUFFER_SIZE; uint8_t *frame_p = FRAME; for(int i = 0; i < NR_CMDS; i++) { unsigned xfer = MIN(IMX233_MAX_SINGLE_DMA_XFER_SIZE, size); lcdif_dma[i].dma.next = &lcdif_dma[(i + 1) % NR_CMDS].dma; lcdif_dma[i].dma.cmd = BF_OR3(APB_CHx_CMD, CHAIN(1), COMMAND(BV_APB_CHx_CMD_COMMAND__READ), XFER_COUNT(xfer)); lcdif_dma[i].dma.buffer = frame_p; size -= xfer; frame_p += xfer; } // first transfer: enable run, dotclk and so on lcdif_dma[0].dma.cmd |= BF_OR1(APB_CHx_CMD, CMDWORDS(1)); lcdif_dma[0].ctrl = BF_OR4(LCDIF_CTRL, BYPASS_COUNT(1), DOTCLK_MODE(1), RUN(1), WORD_LENGTH(1)); // enable lcd_enable(true); }
void imx233_digctl_set_arm_cache_timings(unsigned timings) { #if IMX233_SUBTARGET >= 3780 HW_DIGCTL_ARMCACHE = BF_OR5(DIGCTL_ARMCACHE, ITAG_SS(timings), DTAG_SS(timings), CACHE_SS(timings), DRTY_SS(timings), VALID_SS(timings)); #else HW_DIGCTL_ARMCACHE = BF_OR3(DIGCTL_ARMCACHE, ITAG_SS(timings), DTAG_SS(timings), CACHE_SS(timings)); #endif }
/* volume in half dB * don't check input values */ static void set_dac_vol(int vol_l, int vol_r) { /* minimum is -100dB and max is 0dB */ vol_l = MAX(-200, MIN(vol_l, 0)); vol_r = MAX(-200, MIN(vol_r, 0)); /* unmute, enable zero cross and set volume. * 0xff is 0dB */ HW_AUDIOOUT_DACVOLUME = BF_OR3(AUDIOOUT_DACVOLUME, VOLUME_LEFT(0xff + vol_l), VOLUME_RIGHT(0xff + vol_r), EN_ZCD(1)); }
void imx233_lcdif_setup_dotclk(unsigned v_pulse_width, unsigned v_period, unsigned v_wait_cnt, unsigned v_active, unsigned h_pulse_width, unsigned h_period, unsigned h_wait_cnt, unsigned h_active, bool enable_present) { HW_LCDIF_VDCTRL0 = BF_OR4(LCDIF_VDCTRL0, ENABLE_PRESENT(enable_present), VSYNC_PERIOD_UNIT(1), VSYNC_PULSE_WIDTH_UNIT(1), DOTCLK_V_VALID_DATA_CNT(v_active)); HW_LCDIF_VDCTRL1 = BF_OR2(LCDIF_VDCTRL1, VSYNC_PERIOD(v_period), VSYNC_PULSE_WIDTH(v_pulse_width)); HW_LCDIF_VDCTRL2 = BF_OR3(LCDIF_VDCTRL2, HSYNC_PULSE_WIDTH(h_pulse_width), HSYNC_PERIOD(h_period), DOTCLK_H_VALID_DATA_CNT(h_active)); HW_LCDIF_VDCTRL3 = BF_OR2(LCDIF_VDCTRL3, VERTICAL_WAIT_CNT(v_wait_cnt), HORIZONTAL_WAIT_CNT(h_wait_cnt)); // setup dotclk mode, always bypass count, apparently data select is needed HW_LCDIF_CTRL_SET = BM_OR3(LCDIF_CTRL, DOTCLK_MODE, BYPASS_COUNT, DATA_SELECT); }
/* volume in half dB * don't check input values */ static void set_hp_vol(int vol_l, int vol_r) { /* minimum is -57.5dB and max is 6dB in DAC mode * and -51.5dB / 12dB in Line1 mode */ int min = input_line1 ? -103 : -115; int max = input_line1 ? 24 : 12; vol_l = MAX(min, MIN(vol_l, max)); vol_r = MAX(min, MIN(vol_r, max)); /* unmute, enable zero cross and set volume.*/ #if IMX233_SUBTARGET >= 3700 unsigned mstr_zcd = BM_AUDIOOUT_HPVOL_EN_MSTR_ZCD; #else unsigned mstr_zcd = 0; #endif HW_AUDIOOUT_HPVOL = mstr_zcd | BF_OR3(AUDIOOUT_HPVOL, SELECT(input_line1), VOL_LEFT(max - vol_l), VOL_RIGHT(max - vol_r)); }