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 }
bool headphones_inserted(void) { return !imx233_pinctrl_get_gpio(2, 8); }
static bool i2c_scl_in(void) { return imx233_pinctrl_get_gpio(1, 22); }
static bool i2c_sda_in(void) { return imx233_pinctrl_get_gpio(1, 24); }
bool button_debug_screen(void) { char product_id[RMI_PRODUCT_ID_LEN]; rmi_read(RMI_PRODUCT_ID, RMI_PRODUCT_ID_LEN, product_id); uint8_t product_info[RMI_PRODUCT_INFO_LEN]; rmi_read(RMI_PRODUCT_INFO, RMI_PRODUCT_INFO_LEN, product_info); char product_info_str[RMI_PRODUCT_INFO_LEN * 2 + 1]; for(int i = 0; i < RMI_PRODUCT_INFO_LEN; i++) snprintf(product_info_str + 2 * i, 3, "%02x", product_info[i]); int x_max = rmi_read_single(RMI_2D_SENSOR_XMAX_MSB(0)) << 8 | rmi_read_single(RMI_2D_SENSOR_XMAX_LSB(0)); int y_max = rmi_read_single(RMI_2D_SENSOR_YMAX_MSB(0)) << 8 | rmi_read_single(RMI_2D_SENSOR_YMAX_LSB(0)); int sensor_resol = rmi_read_single(RMI_2D_SENSOR_RESOLUTION(0)); int min_dist = rmi_read_single(RMI_2D_MIN_DIST); int gesture_settings = rmi_read_single(RMI_2D_GESTURE_SETTINGS); int volkeys_delay_counter = 0; union { unsigned char data; signed char value; }sensitivity; rmi_read(RMI_2D_SENSITIVITY_ADJ, 1, &sensitivity.data); /* Device to screen */ int zone_w = LCD_WIDTH; int zone_h = (zone_w * y_max + x_max - 1) / x_max; int zone_x = 0; int zone_y = LCD_HEIGHT - zone_h; #define DX2SX(x) (((x) * zone_w ) / x_max) #define DY2SY(y) (zone_h - ((y) * zone_h ) / y_max) struct viewport report_vp; memset(&report_vp, 0, sizeof(report_vp)); report_vp.x = zone_x; report_vp.y = zone_y; report_vp.width = zone_w; report_vp.height = zone_h; struct viewport gesture_vp; memset(&gesture_vp, 0, sizeof(gesture_vp)); gesture_vp.x = LCD_WIDTH / 2; gesture_vp.y = zone_y - 80; gesture_vp.width = LCD_WIDTH / 2; gesture_vp.height = 80; while(1) { unsigned char sleep_mode = rmi_read_single(RMI_DEVICE_CONTROL) & RMI_SLEEP_MODE_BM; lcd_set_viewport(NULL); lcd_clear_display(); int btns = button_read_device(); lcd_putsf(0, 0, "button bitmap: %x", btns); lcd_putsf(0, 1, "RMI: id=%s info=%s", product_id, product_info_str); lcd_putsf(0, 2, "xmax=%d ymax=%d res=%d", x_max, y_max, sensor_resol); lcd_putsf(0, 3, "attn=%d ctl=%x int=%x", imx233_pinctrl_get_gpio(0, 27) ? 0 : 1, rmi_read_single(RMI_DEVICE_CONTROL), rmi_read_single(RMI_INTERRUPT_REQUEST)); lcd_putsf(0, 4, "sensi: %d min_dist: %d", (int)sensitivity.value, min_dist); lcd_putsf(0, 5, "gesture: %x", gesture_settings); union { unsigned char data[10]; struct { struct rmi_2d_absolute_data_t absolute; struct rmi_2d_relative_data_t relative; struct rmi_2d_gesture_data_t gesture; }s; }u; int absolute_x = u.s.absolute.x_msb << 8 | u.s.absolute.x_lsb; int absolute_y = u.s.absolute.y_msb << 8 | u.s.absolute.y_lsb; int nr_fingers = u.s.absolute.misc & 7; bool gesture = (u.s.absolute.misc & 8) == 8; int palm_width = u.s.absolute.misc >> 4; rmi_read(RMI_DATA_REGISTER(0), 10, u.data); lcd_putsf(0, 6, "abs: %d %d %d", absolute_x, absolute_y, (int)u.s.absolute.z); lcd_putsf(0, 7, "rel: %d %d", (int)u.s.relative.x, (int)u.s.relative.y); lcd_putsf(0, 8, "gesture: %x %x", u.s.gesture.misc, u.s.gesture.flick); lcd_putsf(0, 9, "misc: w=%d g=%d f=%d", palm_width, gesture, nr_fingers); lcd_putsf(30, 7, "sleep_mode: %d", 1 - sleep_mode); lcd_set_viewport(&report_vp); lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0xff, 0, 0), LCD_BLACK); lcd_drawrect(0, 0, zone_w, zone_h); if(nr_fingers == 1) { lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0, 0, 0xff), LCD_BLACK); lcd_drawline(DX2SX(absolute_x) - u.s.relative.x, DY2SY(absolute_y) + u.s.relative.y, DX2SX(absolute_x), DY2SY(absolute_y)); lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0, 0xff, 0), LCD_BLACK); lcd_fillrect(DX2SX(absolute_x) - 1, DY2SY(absolute_y) - 1, 3, 3); } lcd_set_viewport(&gesture_vp); lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0xff, 0xff, 0), LCD_BLACK); if(u.s.gesture.misc & RMI_2D_GEST_MISC_CONFIRMED) { switch(u.s.gesture.misc & RMI_2D_GEST_MISC_TAP_CODE_BM) { case RMI_2D_GEST_MISC_NO_TAP: break; case RMI_2D_GEST_MISC_SINGLE_TAP: lcd_putsf(0, 0, "TAP!"); break; case RMI_2D_GEST_MISC_DOUBLE_TAP: lcd_putsf(0, 0, "DOUBLE TAP!"); break; case RMI_2D_GEST_MISC_TAP_AND_HOLD: lcd_putsf(0, 0, "TAP & HOLD!"); break; default: break; } if(u.s.gesture.misc & RMI_2D_GEST_MISC_FLICK) { lcd_putsf(0, 1, "FLICK!"); int flick_x = u.s.gesture.flick & RMI_2D_GEST_FLICK_X_BM; int flick_y = (u.s.gesture.flick & RMI_2D_GEST_FLICK_Y_BM) >> RMI_2D_GEST_FLICK_Y_BP; #define SIGN4EXT(a) \ if(a & 8) a = -((a ^ 0xf) + 1); SIGN4EXT(flick_x); SIGN4EXT(flick_y); int center_x = (LCD_WIDTH * 2) / 3; int center_y = 40; lcd_drawline(center_x, center_y, center_x + flick_x * 5, center_y - flick_y * 5); } } lcd_update(); if(btns & BUTTON_POWER) break; if(btns & (BUTTON_VOL_DOWN|BUTTON_VOL_UP)) { volkeys_delay_counter++; if(volkeys_delay_counter == 15) { if(btns & BUTTON_VOL_UP) if(sleep_mode > RMI_SLEEP_MODE_FORCE_FULLY_AWAKE) sleep_mode--; if(btns & BUTTON_VOL_DOWN) if(sleep_mode < RMI_SLEEP_MODE_SENSOR_SLEEP) sleep_mode++; rmi_set_sleep_mode(sleep_mode); volkeys_delay_counter = 0; } } yield(); }