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 fmradio_i2c_init(void) { imx233_pinctrl_acquire(1, 24, "fmradio i2c"); imx233_pinctrl_acquire(1, 22, "fmradio i2c"); imx233_pinctrl_set_function(1, 24, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_set_function(1, 22, PINCTRL_FUNCTION_GPIO); fmradio_i2c_bus = i2c_add_node(&fmradio_i2c); }
void __attribute__((weak)) imx233_audio_preinit(void) { #ifdef IMX233_AUDIO_HP_GATE_BANK imx233_pinctrl_acquire(IMX233_AUDIO_HP_GATE_BANK, IMX233_AUDIO_HP_GATE_PIN, "hp_gate"); imx233_pinctrl_set_function(IMX233_AUDIO_HP_GATE_BANK, IMX233_AUDIO_HP_GATE_PIN, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_enable_gpio(IMX233_AUDIO_HP_GATE_BANK, IMX233_AUDIO_HP_GATE_PIN, true); imx233_audio_enable_hp(false); #endif #ifdef IMX233_AUDIO_SPKR_GATE_BANK imx233_pinctrl_acquire(IMX233_AUDIO_SPKR_GATE_BANK, IMX233_AUDIO_SPKR_GATE_PIN, "spkr_gate"); imx233_pinctrl_set_function(IMX233_AUDIO_SPKR_GATE_BANK, IMX233_AUDIO_SPKR_GATE_PIN, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_enable_gpio(IMX233_AUDIO_SPKR_GATE_BANK, IMX233_AUDIO_SPKR_GATE_PIN, true); imx233_audio_enable_spkr(false); #endif }
bool _backlight_init(void) { imx233_pinctrl_acquire(0, 10, "backlight_enable"); imx233_pinctrl_set_function(0, 10, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_enable_gpio(0, 10, true); imx233_pinctrl_set_gpio(0, 10, true); _backlight_set_brightness(DEFAULT_BRIGHTNESS_SETTING); return true; }
/* true after full radio power up, and false before powering down */ void si4700_rds_powerup(bool on) { if(on) { imx233_pinctrl_acquire(2, 27, "tuner stc/rds"); imx233_pinctrl_set_function(2, 27, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_enable_gpio(2, 27, false); /* pin is set to 0 when an RDS packet has arrived */ imx233_pinctrl_setup_irq(2, 27, true, true, false, &stc_rds_callback, 0); } else { imx233_pinctrl_setup_irq(2, 27, false, false, false, NULL, 0); imx233_pinctrl_release(2, 27, "tuner stc/rds"); } }
void imx233_system_prepare_shutdown(void) { /* wait a bit, useful for the user to stop touching anything */ sleep(HZ / 2); /* disable watchdog just in case since we will disable interrupts */ imx233_rtc_enable_watchdog(false); /* disable interrupts, it's probably better to avoid any action so close * to shutdown */ disable_interrupt(IRQ_FIQ_STATUS); #ifdef SANSA_FUZEPLUS /* This pin seems to be important to shutdown the hardware properly */ imx233_pinctrl_acquire(0, 9, "power off"); imx233_pinctrl_set_function(0, 9, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_enable_gpio(0, 9, true); imx233_pinctrl_set_gpio(0, 9, true); #endif }
/* B0P18 is #IRQ line of the touchpad */ void button_init_device(void) { mpr121_init(0xb4); mpr121_soft_reset(); mpr121_set_config(&config); queue_init(&mpr121_queue, true); create_thread(mpr121_thread, mpr121_stack, sizeof(mpr121_stack), 0, mpr121_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); /* enable interrupt */ imx233_pinctrl_acquire(0, 18, "mpr121_int"); imx233_pinctrl_set_function(0, 18, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_enable_gpio(0, 18, false); imx233_pinctrl_setup_irq(0, 18, true, true, false, &mpr121_irq_cb, 0); /* generic part */ imx233_button_init(); }
void lcd_init_device(void) { // determine power type imx233_pinctrl_acquire(3, 16, "lcd power kind"); imx233_pinctrl_set_function(3, 16, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_enable_gpio(3, 16, false); udelay(10); lcd_has_power = !imx233_pinctrl_get_gpio(3, 16); if(lcd_has_power) { imx233_pinctrl_acquire(0, 27, "lcd power"); imx233_pinctrl_set_function(0, 27, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_enable_gpio(0, 27, true); imx233_pinctrl_set_gpio(0, 27, true); } // determine kind (don't acquire pin because it's a lcdif pin !) imx233_pinctrl_set_function(1, 0, PINCTRL_FUNCTION_GPIO); imx233_pinctrl_enable_gpio(1, 0, false); udelay(10); lcd_kind = imx233_pinctrl_get_gpio(1, 0); imx233_lcdif_init(); imx233_lcdif_reset_lcd(false); imx233_lcdif_reset_lcd(true); imx233_lcdif_setup_system_pins(16); imx233_lcdif_set_timings(2, 2, 2, 2); imx233_lcdif_set_word_length(8); // set mux ratio lcd_send(false, 0xca); lcd_send(true, 131); // set remap, color and depth lcd_send(false, 0xa0); lcd_send(true, 0x74); // set master contrast lcd_send(false, 0xc7); lcd_send(true, 0x8); // set V_COMH lcd_send(false, 0xbe); lcd_send(true, lcd_kind ? 0x1c : 0x18); // set color contrasts lcd_send(false, 0xc1); lcd_send(true, 0x7b); lcd_send(true, 0x69); lcd_send(true, lcd_kind ? 0xcf : 0x9f); // set timings lcd_send(false, 0xb1); lcd_send(true, 0x1f); lcd_send(false, 0xb3); lcd_send(true, 0x80); // set precharge voltages lcd_send(false, 0xbb); lcd_send(true, 0x00); lcd_send(true, 0x00); lcd_send(true, 0x00); // set master config lcd_send(false, 0xad); lcd_send(true, 0x8a); // set power saving mode lcd_send(false, 0xb0); lcd_send(true, 0x00); // set normal display (seem to be a SSD1338 only command, not present in SS1339 datasheet) lcd_send(false, 0xd1); lcd_send(true, 0x02); // set LUT lcd_send(false, 0xb8); static uint8_t lut[32] = { 0x01, 0x15, 0x19, 0x1D, 0x21, 0x25, 0x29, 0x2D, 0x31, 0x35, 0x39, 0x3D, 0x41, 0x45, 0x49, 0x4D, 0x51, 0x55, 0x59, 0x5D, 0x61, 0x65, 0x69, 0x6D, 0x71, 0x75, 0x79, 0x7D, 0x81, 0x85, 0x89, 0x8D }; for(int i = 0; i < 32; i++) lcd_send(true, lut[i]); // set display offset (this lcd is really wired strangely) lcd_send(false, 0xa2); lcd_send(true, 128); // normal display lcd_send(false, 0xa6); // sleep mode off lcd_send(false, 0xaf); // write ram lcd_send(false, 0x5c); imx233_lcdif_set_word_length(16); for(int y = 0; y < LCD_HEIGHT; y++) for(int x = 0; x < LCD_WIDTH; x++) { uint16_t v = 0; imx233_lcdif_pio_send(true, 1, &v); } #ifdef HAVE_LCD_ENABLE lcd_on = true; #endif }