diff options
author | Lorenzo Miori <memoryS60@gmail.com> | 2013-09-10 22:48:34 +0200 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2014-02-05 09:56:21 +0100 |
commit | e876f4df6d240bd2e319b1e63be95a625f049a97 (patch) | |
tree | ce2fe1b24650e3be7a6cd2d346d29090a5422a8c /firmware/target | |
parent | b828b9d99bff2acc0e1f543f3176fd4b632cba68 (diff) |
Samsung YP-R1 target port
This is the basic port to the new target Samsung
YP-R1, which runs on a similar platform as YP-R0.
Port is usable, although there are still
some optimizations that have to be done.
Change-Id: If83a8e386369e413581753780c159026d9e41f04
Diffstat (limited to 'firmware/target')
16 files changed, 1397 insertions, 8 deletions
diff --git a/firmware/target/hosted/samsungypr/gpio_ypr.c b/firmware/target/hosted/samsungypr/gpio_ypr.c index 40855fba41..1782d4cfe4 100644 --- a/firmware/target/hosted/samsungypr/gpio_ypr.c +++ b/firmware/target/hosted/samsungypr/gpio_ypr.c @@ -6,7 +6,7 @@ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * - * Module wrapper for GPIO, using /dev/r0GPIO (r0Gpio.ko) of Samsung YP-R0 + * Module wrapper for GPIO, using kernel module of Samsung YP-R0/YP-R1 * * Copyright (c) 2011 Lorenzo Miori * @@ -26,23 +26,23 @@ #include <gpio-target.h> /* includes common ioctl device definitions */ #include <sys/ioctl.h> -static int r0_gpio_dev = 0; +static int gpio_dev = 0; void gpio_init(void) { - r0_gpio_dev = open("/dev/r0GPIO", O_RDONLY); - if (r0_gpio_dev < 0) - printf("/dev/r0GPIO open error!"); + gpio_dev = open(GPIO_DEVICE, O_RDONLY); + if (gpio_dev < 0) + printf("GPIO device open error!"); } void gpio_close(void) { - if (r0_gpio_dev >= 0) - close(r0_gpio_dev); + if (gpio_dev >= 0) + close(gpio_dev); } int gpio_control(int request, int num, int mode, int val) { struct gpio_info r = { .num = num, .mode = mode, .val = val, }; - return ioctl(r0_gpio_dev, request, &r); + return ioctl(gpio_dev, request, &r); } diff --git a/firmware/target/hosted/samsungypr/ypr0/gpio-target.h b/firmware/target/hosted/samsungypr/ypr0/gpio-target.h index c27e07bf40..f27b176195 100644 --- a/firmware/target/hosted/samsungypr/ypr0/gpio-target.h +++ b/firmware/target/hosted/samsungypr/ypr0/gpio-target.h @@ -53,6 +53,7 @@ #define GPIO_LEFT_KEY GPIO2_28 #define GPIO_RIGHT_KEY GPIO3_7 +#define GPIO_DEVICE "/dev/r0GPIO" void gpio_init(void); void gpio_close(void); diff --git a/firmware/target/hosted/samsungypr/ypr1/audio-ypr1.c b/firmware/target/hosted/samsungypr/ypr1/audio-ypr1.c new file mode 100644 index 0000000000..05b77a8ff2 --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/audio-ypr1.c @@ -0,0 +1,76 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2008 by Nils Wallménius + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "config.h" +#include "system.h" +#include "audiohw.h" +#include "audio.h" + +void audiohw_enable_tone_controls(bool enable); +void audiohw_enable_depth_3d(bool enable); + +/* Set the audio source for IIS TX */ +void audio_set_output_source(int source) +{ + switch (source) + { + default: + case AUDIO_SRC_PLAYBACK: + /* + audiohw_enable_tone_controls(true); + audiohw_enable_depth_3d(true); + */ + break; + + case AUDIO_SRC_FMRADIO: + /* Analog path doesn't support these and digital radio playback + * cannot be done without mixing on the MCU if voice is to be + * heard. Any recording should match what is heard. */ + audiohw_enable_tone_controls(false); + audiohw_enable_depth_3d(false); + break; + } +} + +void audio_input_mux(int source, unsigned int flags) +{ + /* Prevent pops from unneeded switching */ + static int last_source = AUDIO_SRC_PLAYBACK; + bool recording = flags & SRCF_RECORDING; + static bool last_recording = false; + + switch (source) + { + default: + source = AUDIO_SRC_PLAYBACK; + /* Fallthrough */ + case AUDIO_SRC_PLAYBACK: /* playback - no recording */ + if (source != last_source) + audiohw_set_recsrc(AUDIO_SRC_PLAYBACK, false); + break; + + case AUDIO_SRC_FMRADIO: /* recording and playback */ + if (source != last_source || recording != last_recording) + audiohw_set_recsrc(AUDIO_SRC_FMRADIO, recording); + break; + } + + last_source = source; + last_recording = recording; +} diff --git a/firmware/target/hosted/samsungypr/ypr1/backlight-ypr1.c b/firmware/target/hosted/samsungypr/ypr1/backlight-ypr1.c new file mode 100644 index 0000000000..e4f0457cf9 --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/backlight-ypr1.c @@ -0,0 +1,66 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2013 by Lorenzo Miori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "config.h" +#include "system.h" +#include "backlight.h" +#include "backlight-target.h" +#include "lcd.h" +#include "lcd-target.h" +#include "pmu-ypr1.h" + +static bool backlight_on_status = true; /* Is on or off? */ + +bool _backlight_init(void) +{ + /* We have nothing to do */ + return true; +} + +void _backlight_on(void) +{ + if (!backlight_on_status) { + _backlight_set_brightness(backlight_brightness); + } + + backlight_on_status = true; + +} + +void _backlight_off(void) +{ + if (backlight_on_status) { + _backlight_set_brightness(0); + } + + backlight_on_status = false; +} + +void _backlight_set_brightness(int brightness) +{ + /* Just another check... */ + if (brightness > MAX_BRIGHTNESS_SETTING) { + brightness = MAX_BRIGHTNESS_SETTING; + } + if (brightness < 0) { + brightness = MIN_BRIGHTNESS_SETTING; + } + /* Do the appropriate ioctl on the linux module */ + pmu_ioctl(MAX8819_IOCTL_LCD_DIM_CTRL, &brightness); +} diff --git a/firmware/target/hosted/samsungypr/ypr1/button-target.h b/firmware/target/hosted/samsungypr/ypr1/button-target.h new file mode 100644 index 0000000000..fc618258c0 --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/button-target.h @@ -0,0 +1,63 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2013 by Lorenzo Miori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _BUTTON_TARGET_H_ +#define _BUTTON_TARGET_H_ + +void button_close_device(void); + +/* Logical buttons key codes */ +#define BUTTON_VOL_UP 0x00000001 +#define BUTTON_VOL_DOWN 0x00000002 +#define BUTTON_POWER 0x00000004 +#define BUTTON_RIGHT 0x00000008 +#define BUTTON_LEFT 0x00000012 + +/* Touch Screen Area Buttons */ +#define BUTTON_TOPLEFT 0x00000010 +#define BUTTON_TOPMIDDLE 0x00000020 +#define BUTTON_TOPRIGHT 0x00000040 +#define BUTTON_MIDLEFT 0x00000080 +#define BUTTON_CENTER 0x00000100 +#define BUTTON_MIDRIGHT 0x00000200 +#define BUTTON_BOTTOMLEFT 0x00000400 +#define BUTTON_BOTTOMMIDDLE 0x00000800 +#define BUTTON_BOTTOMRIGHT 0x00001000 + +/* All the buttons */ +#define BUTTON_MAIN (BUTTON_VOL_UP | BUTTON_VOL_DOWN | BUTTON_POWER | \ + BUTTON_RIGHT|BUTTON_LEFT| BUTTON_TOPLEFT | BUTTON_TOPMIDDLE | \ + BUTTON_TOPRIGHT | BUTTON_MIDLEFT | BUTTON_CENTER | \ + BUTTON_MIDRIGHT | BUTTON_BOTTOMLEFT | BUTTON_BOTTOMMIDDLE | \ + BUTTON_BOTTOMRIGHT) /* all buttons */ + +/* Default touchscreen calibration + * TODO this is not 100% accurate. X-AXIS must be slightly moved to the right + */ +#define DEFAULT_TOUCHSCREEN_CALIBRATION {.A=0x0000AD7C, .B=0xFFFFFC70, \ + .C=0xFF6632E0, .D=0xFFFFFF1A, .E=0xFFFF5D08, \ + .F=0xFFFC4230, .divider=0xFFFF54E0} + +/* Software power-off */ +#define POWEROFF_BUTTON BUTTON_POWER +/* About 3 seconds */ +#define POWEROFF_COUNT 10 + +#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/hosted/samsungypr/ypr1/button-ypr1.c b/firmware/target/hosted/samsungypr/ypr1/button-ypr1.c new file mode 100644 index 0000000000..09891cfaf6 --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/button-ypr1.c @@ -0,0 +1,130 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: button-sdl.c 30482 2011-09-08 14:53:28Z kugel $ + * + * Copyright (C) 2013 Lorenzo Miori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "config.h" +#include "button.h" +#include "kernel.h" +#include "system.h" +#include "button-target.h" + +#include <gpio-target.h> /* For headphones sense and buttons */ +#include "mcs5000.h" /* Touchscreen controller */ +#include "ioctl-ypr1.h" + +enum { + STATE_UNKNOWN, + STATE_UP, + STATE_DOWN, +}; + +static int last_x = 0; +static int last_y = 0; +static int last_touch_state = STATE_UNKNOWN; + +int button_read_device(int *data) +{ + int key = BUTTON_NONE; + int read_size; + struct mcs5000_raw_data touchpad_data; + + /* Check for all the keys */ + if (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_VOL_UP_KEY, 0, 0)) { + key |= BUTTON_VOL_UP; + } + if (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_VOL_DOWN_KEY, 0, 0)) { + key |= BUTTON_VOL_DOWN; + } + if (gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_POWER_KEY, 0, 0)) { + key |= BUTTON_POWER; + } + + read_size = mcs5000_read(&touchpad_data); + + if (read_size == sizeof(struct mcs5000_raw_data)) { + /* Generate UP and DOWN events */ + if (touchpad_data.inputInfo & INPUT_TYPE_SINGLE) { + last_touch_state = STATE_DOWN; + } + else { + last_touch_state = STATE_UP; + } + /* Swap coordinates here */ +#if CONFIG_ORIENTATION == SCREEN_PORTRAIT + last_x = (touchpad_data.yHigh << 8) | touchpad_data.yLow; + last_y = (touchpad_data.xHigh << 8) | touchpad_data.xLow; +#else + last_x = (touchpad_data.xHigh << 8) | touchpad_data.xLow; + last_y = (touchpad_data.yHigh << 8) | touchpad_data.yLow; +#endif + } + + int tkey = touchscreen_to_pixels(last_x, last_y, data); + + if (last_touch_state == STATE_DOWN) { + key |= tkey; + } + + return key; +} + +#ifndef HAS_BUTTON_HOLD +void touchscreen_enable_device(bool en) +{ + if (en) { + mcs5000_power(); + } + else { + mcs5000_shutdown(); + } +} +#endif + +bool headphones_inserted(void) +{ + /* GPIO low - 0 - means headphones inserted */ + return !gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_HEADPHONE_SENSE, 0, 0); +} + +void button_init_device(void) +{ + /* Setup GPIO pin for headphone sense, copied from OF + * Pins for the other buttons are already set up by OF button module + */ + gpio_control(DEV_CTRL_GPIO_SET_MUX, GPIO_HEADPHONE_SENSE, 4, 0); + gpio_control(DEV_CTRL_GPIO_SET_INPUT, GPIO_HEADPHONE_SENSE, 4, 0); + + /* Turn on touchscreen */ + mcs5000_init(); + mcs5000_power(); + mcs5000_set_hand(RIGHT_HAND); +} + +#ifdef BUTTON_DRIVER_CLOSE +/* I'm not sure it's called at shutdown...give a check! */ +void button_close_device(void) +{ + gpio_control(DEV_CTRL_GPIO_UNSET_MUX, GPIO_HEADPHONE_SENSE, 0, 0); + + /* Turn off touchscreen device */ + mcs5000_shutdown(); + mcs5000_close(); +} +#endif /* BUTTON_DRIVER_CLOSE */ diff --git a/firmware/target/hosted/samsungypr/ypr1/gpio-target.h b/firmware/target/hosted/samsungypr/ypr1/gpio-target.h new file mode 100644 index 0000000000..f439e786de --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/gpio-target.h @@ -0,0 +1,67 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Module wrapper for GPIO, using /dev/r1GPIO (r1Gpio.ko) of Samsung YP-R1 + * + * Copyright (c) 2013 Lorenzo Miori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef GPIO_TARGET_H +#define GPIO_TARGET_H + +#include "ioctl-ypr1.h" + +/* Some meaningful pins used in the YP-R1 */ + +#define GPIO_HEADPHONE_SENSE GPIO1_31 +/* I2C bus for the SI4079 FM, WM1808 codec and RTC radio chip */ +#define GPIO_I2C_CLK1 GPIO1_0 +#define GPIO_I2C_DAT1 GPIO1_1 +/* I2C bus for the fuel gauge MAX17040 */ +#define GPIO_I2C_CLK2 GPIO2_12 +#define GPIO_I2C_DAT2 GPIO2_13 +/* SI4079 pins - powerup and interrupt */ +#define GPIO_FM_SEARCH GPIO1_4 +#define GPIO_FM_BUS_EN GPIO1_10 +#define GPIO_MUTE GPIO2_17 +#define EXT_POWER_DET GPIO1_26 +/* Low disabled, high enabled */ +#define TV_OUT_ENABLE GPIO1_17 +/* Battery charging */ +#define CHARGE_ENABLE GPIO1_18 +#define CHARGE_STATUS GPIO_D13 +/* This should be high when connecting a special port to the board... */ +#define PBA_CHECK_ENABLED GPIO2_1 +/* TODO see if this is the source of massive battery drain + * touchscreen and usb 3.3v power control line + */ +#define POWER_3V3_LINE_CONTROL GPIO1_16 + +/* Keypad */ + +#define GPIO_VOL_UP_KEY GPIO1_20 +#define GPIO_VOL_DOWN_KEY GPIO1_21 +#define GPIO_POWER_KEY GPIO2_16 + +#define GPIO_DEVICE "/dev/r1Gpio" + +void gpio_init(void); +void gpio_close(void); +int gpio_control_struct(int request, struct gpio_info pin); +int gpio_control(int request, int num, int mode, int val); + +#endif /* GPIO_TARGET_H */ diff --git a/firmware/target/hosted/samsungypr/ypr1/ioctl-ypr1.h b/firmware/target/hosted/samsungypr/ypr1/ioctl-ypr1.h new file mode 100644 index 0000000000..4ac7a1c4b5 --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/ioctl-ypr1.h @@ -0,0 +1,230 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2013 Lorenzo Miori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef __DEV_IOCTL_YPR0_H__ +#define __DEV_IOCTL_YPR0_H__ + +#include <sys/ioctl.h> +#include "stdint.h" + +/** + * This is the wrapper to r1Bat.ko module with the possible + * ioctl calls, retrieved by RE + * The "Fuel gauge" - battery controller - is the MAX17040GT + */ + +/* A typical read spans 2 registers */ +typedef struct { + uint8_t addr; + uint8_t reg1; + uint8_t reg2; +}__attribute__((packed)) max17040_request; + +/* Registers are 16-bit wide */ +#define MAX17040_GET_BATTERY_VOLTAGE 0x80045800 +#define MAX17040_GET_BATTERY_CAPACITY 0x80045801 +#define MAX17040_READ_REG 0x80035803 +#define MAX17040_WRITE_REG 0x40035802 + +void max17040_init(void); +void max17040_close(void); +int max17040_ioctl(int request, int *data); + +/** + * This is the wrapper to r1Gpio.ko module with the possible + * ioctl calls + * TODO move this into a more generic file for ypr platform + */ + +struct gpio_info { + int num; + int mode; + int val; +} __attribute__((packed)); + +/* Strangely for whatever reason magic differs from R0 (A vs. G) */ +#define IOCTL_GPIO_MAGIC 'A' + +#define E_IOCTL_GPIO_SET_MUX 0 +#define E_IOCTL_GPIO_UNSET_MUX 1 +#define E_IOCTL_GPIO_SET_TYPE 2 +#define E_IOCTL_GPIO_SET_OUTPUT 3 +#define E_IOCTL_GPIO_SET_INPUT 4 +#define E_IOCTL_GPIO_SET_HIGH 5 +#define E_IOCTL_GPIO_SET_LOW 6 +#define E_IOCTL_GPIO_GET_VAL 7 +#define E_IOCTL_GPIO_IS_HIGH 8 +#define E_IOCTL_GPIO_MAX_NR 9 + +#define DEV_CTRL_GPIO_SET_MUX _IOW(IOCTL_GPIO_MAGIC, 0, struct gpio_info) +#define DEV_CTRL_GPIO_UNSET_MUX _IOW(IOCTL_GPIO_MAGIC, 1, struct gpio_info) +#define DEV_CTRL_GPIO_SET_TYPE _IOW(IOCTL_GPIO_MAGIC, 2, struct gpio_info) +#define DEV_CTRL_GPIO_SET_OUTPUT _IOW(IOCTL_GPIO_MAGIC, 3, struct gpio_info) +#define DEV_CTRL_GPIO_SET_INPUT _IOW(IOCTL_GPIO_MAGIC, 4, struct gpio_info) +#define DEV_CTRL_GPIO_SET_HIGH _IOW(IOCTL_GPIO_MAGIC, 5, struct gpio_info) +#define DEV_CTRL_GPIO_SET_LOW _IOW(IOCTL_GPIO_MAGIC, 6, struct gpio_info) +#define DEV_CTRL_GPIO_GET_VAL _IOW(IOCTL_GPIO_MAGIC, 7, struct gpio_info) +#define DEV_CTRL_GPIO_IS_HIGH _IOW(IOCTL_GPIO_MAGIC, 8, struct gpio_info) + + +typedef enum +{ + GPIO1_0 = 0, /* GPIO group 1 start */ + GPIO1_1, + GPIO1_2, + GPIO1_3, + GPIO1_4, + GPIO1_5, + GPIO1_6, + GPIO1_7, + GPIO1_8, + GPIO1_9, + GPIO1_10, + GPIO1_11, + GPIO1_12, + GPIO1_13, + GPIO1_14, + GPIO1_15, + GPIO1_16, + GPIO1_17, + GPIO1_18, + GPIO1_19, + GPIO1_20, + GPIO1_21, + GPIO1_22, + GPIO1_23, + GPIO1_24, + GPIO1_25, + GPIO1_26, + GPIO1_27, + GPIO1_28, + GPIO1_29, + GPIO1_30, + GPIO1_31, + GPIO2_0, /* GPIO group 2 start */ + GPIO2_1, + GPIO2_2, + GPIO2_3, + GPIO2_4, + GPIO2_5, + GPIO2_6, + GPIO2_7, + GPIO2_8, + GPIO2_9, + GPIO2_10, + GPIO2_11, + GPIO2_12, + GPIO2_13, + GPIO2_14, + GPIO2_15, + GPIO2_16, + GPIO2_17, + GPIO2_18, + GPIO2_19, + GPIO2_20, + GPIO2_21, + GPIO2_22, + GPIO2_23, + GPIO2_24, + GPIO2_25, + GPIO2_26, + GPIO2_27, + GPIO2_28, + GPIO2_29, + GPIO2_30, + GPIO2_31, + GPIO3_0, /* GPIO group 3 start */ + GPIO3_1, + GPIO3_2, + GPIO3_3, + GPIO3_4, + GPIO3_5, + GPIO3_6, + GPIO3_7, + GPIO3_8, + GPIO3_9, + GPIO3_10, + GPIO3_11, + GPIO3_12, + GPIO3_13, + GPIO3_14, + GPIO3_15, + GPIO3_16, + GPIO3_17, + GPIO3_18, + GPIO3_19, + GPIO3_20, + GPIO3_21, + GPIO3_22, + GPIO3_23, + GPIO3_24, + GPIO3_25, + GPIO3_26, + GPIO3_27, + GPIO3_28, + GPIO3_29, + GPIO3_30, + GPIO3_31, +}R0_MX37_GPIO; + +typedef enum +{ + CONFIG_ALT0, + CONFIG_ALT1, + CONFIG_ALT2, + CONFIG_ALT3, + CONFIG_ALT4, + CONFIG_ALT5, + CONFIG_ALT6, + CONFIG_ALT7, + CONFIG_GPIO, + CONFIG_SION = 0x01 << 4, + CONFIG_DEFAULT +} R0_MX37_PIN_CONFIG; + +#ifndef __MACH_MX37_IOMUX_H__ +typedef enum +{ + PAD_CTL_SRE_SLOW = 0x0 << 0, + PAD_CTL_SRE_FAST = 0x1 << 0, + PAD_CTL_DRV_LOW = 0x0 << 1, + PAD_CTL_DRV_MEDIUM = 0x1 << 1, + PAD_CTL_DRV_HIGH = 0x2 << 1, + PAD_CTL_DRV_MAX = 0x3 << 1, + PAD_CTL_ODE_OPENDRAIN_NONE = 0x0 << 3, + PAD_CTL_ODE_OPENDRAIN_ENABLE = 0x1 << 3, + PAD_CTL_100K_PD = 0x0 << 4, + PAD_CTL_47K_PU = 0x1 << 4, + PAD_CTL_100K_PU = 0x2 << 4, + PAD_CTL_22K_PU = 0x3 << 4, + PAD_CTL_PUE_KEEPER = 0x0 << 6, + PAD_CTL_PUE_PULL = 0x1 << 6, + PAD_CTL_PKE_NONE = 0x0 << 7, + PAD_CTL_PKE_ENABLE = 0x1 << 7, + PAD_CTL_HYS_NONE = 0x0 << 8, + PAD_CTL_HYS_ENABLE = 0x1 << 8, + PAD_CTL_DDR_INPUT_CMOS = 0x0 << 9, + PAD_CTL_DDR_INPUT_DDR = 0x1 << 9, + PAD_CTL_DRV_VOT_LOW = 0x0 << 13, + PAD_CTL_DRV_VOT_HIGH = 0x1 << 13, +} R0_MX37_PAD_CONFIG; +#endif + +#endif /* __DEV_IOCTL_YPR0_H__ */ diff --git a/firmware/target/hosted/samsungypr/ypr1/mcs5000-ypr1.c b/firmware/target/hosted/samsungypr/ypr1/mcs5000-ypr1.c new file mode 100644 index 0000000000..bfd9922768 --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/mcs5000-ypr1.c @@ -0,0 +1,94 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (c) 2013 Lorenzo Miori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include <unistd.h> +#include <fcntl.h> +#include "sys/ioctl.h" + +#include "mcs5000.h" +#include "ioctl-ypr1.h" + +/* TODO Settings like hand and sensitivity will be lost when shutting device off!! */ + +static int mcs5000_dev = -1; +static int mcs5000_hand_setting = RIGHT_HAND; + +void mcs5000_init(void) +{ + mcs5000_dev = open("/dev/r1Touch", O_RDONLY); +} + +void mcs5000_close(void) +{ + if (mcs5000_dev > 0) + close(mcs5000_dev); +} + +void mcs5000_power(void) +{ + ioctl(mcs5000_dev, DEV_CTRL_TOUCH_ON); + ioctl(mcs5000_dev, DEV_CTRL_TOUCH_IDLE); + mcs5000_set_hand(mcs5000_hand_setting); +} + +void mcs5000_shutdown(void) +{ + /* save setting before shutting down the device */ + ioctl(mcs5000_dev, DEV_CTRL_TOUCH_FLUSH); + ioctl(mcs5000_dev, DEV_CTRL_TOUCH_RESET); + ioctl(mcs5000_dev, DEV_CTRL_TOUCH_OFF); +} + +void mcs5000_set_hand(int hand) +{ + switch (hand) + { + case RIGHT_HAND: + ioctl(mcs5000_dev, DEV_CTRL_TOUCH_RIGHTHAND); + break; + case LEFT_HAND: + ioctl(mcs5000_dev, DEV_CTRL_TOUCH_LEFTHAND); + break; + default: + break; + } + mcs5000_hand_setting = hand; +} + +void mcs5000_set_sensitivity(int level) +{ + ioctl(mcs5000_dev, DEV_CTRL_TOUCH_SET_SENSE, &level); +} + +int mcs5000_read(struct mcs5000_raw_data *touchData) +{ + /* work around GCC bug: aligned attribute is not applied to automatic + * variables, and apparently this structure has a large alignment requirement + * (if it's only automatic with implicit 8-byte alignment then the + * touchscreen misbehaves). The bug seems fixed in gcc 4.6.x + * See http://http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660 + * Also: packet and aligned attributes don't really work together so + * the aligned attribute cannot be attached to the struct declaration */ + static struct mcs5000_raw_data touchpad_data __attribute__((aligned(256))); + ssize_t ret; + ret = read(mcs5000_dev, &touchpad_data, sizeof(struct mcs5000_raw_data)); + *touchData = touchpad_data; + return ret; +} diff --git a/firmware/target/hosted/samsungypr/ypr1/mcs5000.h b/firmware/target/hosted/samsungypr/ypr1/mcs5000.h new file mode 100644 index 0000000000..45cce19a32 --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/mcs5000.h @@ -0,0 +1,189 @@ + /* + * Unfortunately I couldn't find any datasheet for this touch controller nor + * any other information. I tried to send Melfas an email but their servers + * seem to be full in this period. The best thing I could find is a Linux + * driver written by Samsung. + * In the opensource package for YP-R1 there are also some more information + * in the file r1TouchMelfasReg.h, which at the moment are not used (I2C stuff + * and error codes) + * + * The rest, function definitions, are written by me (Lorenzo Miori) + * + * mcs5000_ts.c - Touchscreen driver for MELFAS MCS-5000 controller + * + * Copyright (C) 2009 Samsung Electronics Co.Ltd + * Author: Joonyoung Shim <jy0922.shim@samsung.com> + * + * Based on wm97xx-core.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +/** + * This is the wrapper to r1Touch.ko module with the possible + * ioctl calls + * The touchscreen controller is the Melfas MCS5000 + */ + +#define MCS5000_IOCTL_MAGIC 'X' + +#define MCS5000_IOCTL_TOUCH_RESET 0 +#define MCS5000_IOCTL_TOUCH_ON 1 +#define MCS5000_IOCTL_TOUCH_OFF 2 +#define MCS5000_IOCTL_TOUCH_FLUSH 3 +#define MCS5000_IOCTL_TOUCH_SLEEP 4 +#define MCS5000_IOCTL_TOUCH_WAKE 5 +#define MCS5000_IOCTL_TOUCH_ENTER_FWUPG_MODE 6 +#define MCS5000_IOCTL_TOUCH_I2C_READ 7 +#define MCS5000_IOCTL_TOUCH_I2C_WRITE 8 +#define MCS5000_IOCTL_TOUCH_RESET_AFTER_FWUPG 9 +#define MCS5000_IOCTL_TOUCH_RIGHTHAND 10 +#define MCS5000_IOCTL_TOUCH_LEFTHAND 11 +#define MCS5000_IOCTL_TOUCH_IDLE 12 +#define MCS5000_IOCTL_TOUCH_SET_SENSE 13 +#define MCS5000_IOCTL_TOUCH_GET_VER 14 +#define MCS5000_IOCTL_TOUCH_SET_REP_RATE 15 +#define MCS5000_IOCTL_TOUCH_ENABLE_WDOG 16 +#define MCS5000_IOCTL_TOUCH_DISABLE_WDOG 17 + +struct mcs5000_i2c_data +{ + int count; + unsigned char addr; + unsigned char pData[256]; +} __attribute__((packed)); + +#define DEV_CTRL_TOUCH_RESET _IO(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_RESET) +#define DEV_CTRL_TOUCH_ON _IO(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_ON) +#define DEV_CTRL_TOUCH_OFF _IO(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_OFF) +#define DEV_CTRL_TOUCH_FLUSH _IO(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_FLUSH) +#define DEV_CTRL_TOUCH_SLEEP _IO(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_SLEEP) +#define DEV_CTRL_TOUCH_WAKE _IO(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_WAKE) +#define DEV_CTRL_TOUCH_ENTER_FWUPG_MODE _IO(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_ENTER_FWUPG_MODE) +#define DEV_CTRL_TOUCH_I2C_READ _IOWR(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_I2C_READ, mcs5000_i2c_data) +#define DEV_CTRL_TOUCH_I2C_WRITE _IOWR(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_I2C_WRITE, mcs5000_i2c_data) +#define DEV_CTRL_TOUCH_RESET_AFTER_FWUPG _IO(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_RESET_AFTER_FWUPG) +#define DEV_CTRL_TOUCH_RIGHTHAND _IO(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_RIGHTHAND) +#define DEV_CTRL_TOUCH_LEFTHAND _IO(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_LEFTHAND) +#define DEV_CTRL_TOUCH_IDLE _IO(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_IDLE) +#define DEV_CTRL_TOUCH_SET_SENSE _IOW(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_SET_SENSE, int) +#define DEV_CTRL_TOUCH_GET_VER _IOR(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_GET_VER, int) +#define DEV_CTRL_TOUCH_SET_REP_RATE _IOW(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_SET_REP_RATE, int) +#define DEV_CTRL_TOUCH_ENABLE_WDOG _IO(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_ENABLE_WDOG) +#define DEV_CTRL_TOUCH_DISABLE_WDOG _IO(MCS5000_IOCTL_MAGIC, MCS5000_IOCTL_TOUCH_DISABLE_WDOG) +#define DEV_CTRL_TOUCH_MAX_NR 18 + +/* Register definitions */ +#define MCS5000_TS_STATUS 0x00 +#define STATUS_OFFSET 0 +#define STATUS_NO (0 << STATUS_OFFSET) +#define STATUS_INIT (1 << STATUS_OFFSET) +#define STATUS_SENSING (2 << STATUS_OFFSET) +#define STATUS_COORD (3 << STATUS_OFFSET) +#define STATUS_GESTURE (4 << STATUS_OFFSET) +#define ERROR_OFFSET 4 +#define ERROR_NO (0 << ERROR_OFFSET) +#define ERROR_POWER_ON_RESET (1 << ERROR_OFFSET) +#define ERROR_INT_RESET (2 << ERROR_OFFSET) +#define ERROR_EXT_RESET (3 << ERROR_OFFSET) +#define ERROR_INVALID_REG_ADDRESS (8 << ERROR_OFFSET) +#define ERROR_INVALID_REG_VALUE (9 << ERROR_OFFSET) + +#define MCS5000_TS_OP_MODE 0x01 +#define RESET_OFFSET 0 +#define RESET_NO (0 << RESET_OFFSET) +#define RESET_EXT_SOFT (1 << RESET_OFFSET) +#define OP_MODE_OFFSET 1 +#define OP_MODE_SLEEP (0 << OP_MODE_OFFSET) +#define OP_MODE_ACTIVE (1 << OP_MODE_OFFSET) +#define GESTURE_OFFSET 4 +#define GESTURE_DISABLE (0 << GESTURE_OFFSET) +#define GESTURE_ENABLE (1 << GESTURE_OFFSET) +#define PROXIMITY_OFFSET 5 +#define PROXIMITY_DISABLE (0 << PROXIMITY_OFFSET) +#define PROXIMITY_ENABLE (1 << PROXIMITY_OFFSET) +#define SCAN_MODE_OFFSET 6 +#define SCAN_MODE_INTERRUPT (0 << SCAN_MODE_OFFSET) +#define SCAN_MODE_POLLING (1 << SCAN_MODE_OFFSET) +#define REPORT_RATE_OFFSET 7 +#define REPORT_RATE_40 (0 << REPORT_RATE_OFFSET) +#define REPORT_RATE_80 (1 << REPORT_RATE_OFFSET) + +#define MCS5000_TS_SENS_CTL 0x02 +#define MCS5000_TS_FILTER_CTL 0x03 +#define PRI_FILTER_OFFSET 0 +#define SEC_FILTER_OFFSET 4 + +#define MCS5000_TS_X_SIZE_UPPER 0x08 +#define MCS5000_TS_X_SIZE_LOWER 0x09 +#define MCS5000_TS_Y_SIZE_UPPER 0x0A +#define MCS5000_TS_Y_SIZE_LOWER 0x0B + +#define MCS5000_TS_INPUT_INFO 0x10 +#define INPUT_TYPE_OFFSET 0 +#define INPUT_TYPE_NONTOUCH (0 << INPUT_TYPE_OFFSET) +#define INPUT_TYPE_SINGLE (1 << INPUT_TYPE_OFFSET) +#define INPUT_TYPE_DUAL (2 << INPUT_TYPE_OFFSET) +#define INPUT_TYPE_PALM (3 << INPUT_TYPE_OFFSET) +#define INPUT_TYPE_PROXIMITY (7 << INPUT_TYPE_OFFSET) +#define GESTURE_CODE_OFFSET 3 +#define GESTURE_CODE_NO (0 << GESTURE_CODE_OFFSET) + +#define MCS5000_TS_X_POS_UPPER 0x11 +#define MCS5000_TS_X_POS_LOWER 0x12 +#define MCS5000_TS_Y_POS_UPPER 0x13 +#define MCS5000_TS_Y_POS_LOWER 0x14 +#define MCS5000_TS_Z_POS 0x15 +#define MCS5000_TS_WIDTH 0x16 +#define MCS5000_TS_GESTURE_VAL 0x17 +#define MCS5000_TS_MODULE_REV 0x20 +#define MCS5000_TS_FIRMWARE_VER 0x21 + +/* Touchscreen absolute values */ +#define MCS5000_MAX_XC 0x3ff +#define MCS5000_MAX_YC 0x3ff + +/* this struct also seems to have an alignment requirement (256-byte aligned?). + * touchscreen won't work correctly with 8-byte alignment. The aligned attribute + * cannot be attached here because it would make the struct larger and packed + * be ignored. + * See also mcs5000_read() */ +struct mcs5000_raw_data +{ + unsigned char inputInfo; + unsigned char xHigh; + unsigned char xLow; + unsigned char yHigh; + unsigned char yLow; + unsigned char z; + unsigned char width; + unsigned char gesture; +} __attribute__((packed)); + +/** + * Two possibilities for hand usage + */ +enum +{ + RIGHT_HAND, + LEFT_HAND, +}; + +/* Open device */ +void mcs5000_init(void); +/* Close device */ +void mcs5000_close(void); +/* Power up the chip (voltages) */ +void mcs5000_power(void); +/* Shutdown the chip (voltages) */ +void mcs5000_shutdown(void); +/* Set user hand usage */ +void mcs5000_set_hand(int hand_setting); +/* Set touchscreen sensitivity. Valid values are 1,2,4,8 */ +void mcs5000_set_sensitivity(int level); +/* Read controller's data */ +int mcs5000_read(struct mcs5000_raw_data *touchData); diff --git a/firmware/target/hosted/samsungypr/ypr1/pmu-ypr1.c b/firmware/target/hosted/samsungypr/ypr1/pmu-ypr1.c new file mode 100644 index 0000000000..8a2a724ca4 --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/pmu-ypr1.c @@ -0,0 +1,51 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2013 Lorenzo Miori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> + +#include "pmu-ypr1.h" +#include "panic.h" + +static int pmu_dev = -1; + +void pmu_init(void) +{ + pmu_dev = open("/dev/r1Pmu", O_RDONLY); + if (pmu_dev < 0) + panicf("/dev/r1Pmu open error!"); +} + +void pmu_close(void) +{ + if (pmu_dev >= 0) + close(pmu_dev); +} + +int pmu_get_dev(void) +{ + return pmu_dev; +} + +int pmu_ioctl(int request, int *data) +{ + return ioctl(pmu_dev, request, data); +} diff --git a/firmware/target/hosted/samsungypr/ypr1/pmu-ypr1.h b/firmware/target/hosted/samsungypr/ypr1/pmu-ypr1.h new file mode 100644 index 0000000000..e8103f22c9 --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/pmu-ypr1.h @@ -0,0 +1,88 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2013 Lorenzo Miori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef __PMU_YPR1_H__ +#define __PMU_YPR1_H__ + +#include "sys/ioctl.h" + +/** + * This is the wrapper to r1Pmu.ko module with the possible + * ioctl calls + * The PMU controller is the MAX8819 + */ + +#define MAX8819_IOCTL_MAGIC 'A' + +#define E_MAX8819_IOCTL_GET_BATT_LVL 0 +#define E_MAX8819_IOCTL_GET_CHG_STATUS 1 +#define E_MAX8819_IOCTL_IS_EXT_PWR 2 +#define E_MAX8819_IOCTL_STOP_CHG 3 +#define E_MAX8819_IOCTL_START_CHG 4 +#define E_MAX8819_IOCTL_IS_EXT_PWR_OVP 5 +#define E_MAX8819_IOCTL_LCD_DIM_CTRL 6 +#define E_MAX8819_IOCTL_CORE_CTL_HIGH 7 +#define E_MAX8819_IOCTL_CORE_CTL_LOW 8 +#define E_MAX8819_IOCTL_TSP_USB_PWR_OFF 9 + +#define MAX8819_IOCTL_GET_BATT_LVL _IO(MAX8819_IOCTL_MAGIC, E_MAX8819_IOCTL_GET_BATT_LVL) +#define MAX8819_IOCTL_GET_CHG_STATUS _IO(MAX8819_IOCTL_MAGIC, E_MAX8819_IOCTL_GET_CHG_STATUS) +#define MAX8819_IOCTL_IS_EXT_PWR _IO(MAX8819_IOCTL_MAGIC, E_MAX8819_IOCTL_IS_EXT_PWR) +#define MAX8819_IOCTL_STOP_CHG _IO(MAX8819_IOCTL_MAGIC, E_MAX8819_IOCTL_STOP_CHG) +#define MAX8819_IOCTL_START_CHG _IO(MAX8819_IOCTL_MAGIC, E_MAX8819_IOCTL_START_CHG) +#define MAX8819_IOCTL_IS_EXT_PWR_OVP _IO(MAX8819_IOCTL_MAGIC, E_MAX8819_IOCTL_IS_EXT_PWR_OVP) +#define MAX8819_IOCTL_LCD_DIM_CTRL _IOW(MAX8819_IOCTL_MAGIC, E_MAX8819_IOCTL_LCD_DIM_CTRL, int) +#define MAX8819_IOCTL_CORE_CTL_HIGH _IO(MAX8819_IOCTL_MAGIC, E_MAX8819_IOCTL_CORE_CTL_HIGH) +#define MAX8819_IOCTL_CORE_CTL_LOW _IO(MAX8819_IOCTL_MAGIC, E_MAX8819_IOCTL_CORE_CTL_LOW) +#define MAX8819_IOCTL_TSP_USB_PWR_OFF _IO(MAX8819_IOCTL_MAGIC, E_MAX8819_IOCTL_TSP_USB_PWR_OFF) + +#define MAX8819_IOCTL_MAX_NR (E_MAX8819_IOCTL_TSP_USB_PWR_OFF+1) + +enum +{ + EXT_PWR_UNPLUGGED = 0, + EXT_PWR_PLUGGED, + EXT_PWR_NOT_OVP, + EXT_PWR_OVP, +}; + +enum +{ + PMU_CHARGING = 0, + PMU_NOT_CHARGING, + PMU_FULLY_CHARGED, +}; + +enum +{ + BATT_LVL_OFF = 0, + BATT_LVL_WARN, + BATT_LVL_1, + BATT_LVL_2, + BATT_LVL_3, + BATT_LVL_4, +}; + +void pmu_init(void); +void pmu_close(void); +int pmu_get_dev(void); +int pmu_ioctl(int request, int *data); + +#endif diff --git a/firmware/target/hosted/samsungypr/ypr1/powermgmt-ypr1.c b/firmware/target/hosted/samsungypr/ypr1/powermgmt-ypr1.c new file mode 100644 index 0000000000..9a8f9747ae --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/powermgmt-ypr1.c @@ -0,0 +1,153 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2013 Lorenzo Miori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "config.h" +#include <sys/ioctl.h> +#include "kernel.h" +#include "powermgmt.h" +#include "power.h" +#include "file.h" +#include "adc.h" +#include "radio-ypr.h" +#include "pmu-ypr1.h" +#include "ioctl-ypr1.h" +#include "stdio.h" +#include "unistd.h" +#include "fcntl.h" +#include "system.h" + +#define MAX17040_VCELL 0x02 +#define MAX17040_SOC 0x04 +#define MAX17040_MODE 0x06 +#define MAX17040_VERSION 0x08 +#define MAX17040_RCOMP 0x0C +#define MAX17040_COMMAND 0xFE + +static int max17040_dev = -1; + +void max17040_init(void) +{ + max17040_dev = open("/dev/r1Batt", O_RDONLY); + if (max17040_dev < 0) + printf("/dev/r1Batt open error!"); +} + +void max17040_close(void) +{ + if (max17040_dev >= 0) + close(max17040_dev); +} + +#if (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) == VOLTAGE_MEASURE +const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = +{ + 3470 +}; + +/* the OF shuts down at this voltage */ +const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = +{ + 3450 +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ +const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +{ + { 3450, 3502, 3550, 3587, 3623, 3669, 3742, 3836, 3926, 4026, 4200 } +}; +#endif + +#if CONFIG_CHARGING +/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ +const unsigned short const percent_to_volt_charge[11] = +{ + 3450, 3670, 3721, 3751, 3782, 3821, 3876, 3941, 4034, 4125, 4200 +}; + +unsigned int power_input_status(void) +{ + unsigned status = POWER_INPUT_NONE; + if (pmu_ioctl(MAX8819_IOCTL_IS_EXT_PWR, NULL) > 0) + status = POWER_INPUT_MAIN_CHARGER; + return status; +} + +#endif /* CONFIG_CHARGING */ + +/* Returns battery voltage from MAX17040 VCELL ADC [millivolts steps], + * adc returns voltage in 1.25mV steps */ +/* + * TODO this would be interesting to be mixed with battery percentage, for information + * and completition purpouses + */ +#if (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) == VOLTAGE_MEASURE +int _battery_voltage(void) +{ + int level = 4000; + max17040_request ret = { .addr = 2, .reg1 = 0, .reg2 = 0 }; + if (ioctl(max17040_dev, MAX17040_READ_REG, &ret) >= 0) + { + int step = (ret.reg1 << 4) | (ret.reg2 >> 4); + level = step + (step >> 2); + } + return level; +} +#elif (CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) == PERCENTAGE_MEASURE +int _battery_level(void) +{ + int level = 100; + max17040_request ret = { .addr = 4, .reg1 = 0, .reg2 = 0 }; + if (ioctl(max17040_dev, MAX17040_READ_REG, &ret) >= 0) + level = MIN(ret.reg1, 100); + return level; +} +#endif + +bool charging_state(void) +{ + int ret = pmu_ioctl(MAX8819_IOCTL_GET_CHG_STATUS, NULL); + if (ret == PMU_FULLY_CHARGED) + return true; + return false; +} + +#if CONFIG_TUNER +static bool tuner_on = false; + +bool tuner_power(bool status) +{ + if (status != tuner_on) + { + tuner_on = status; + status = !status; + if (tuner_on) + radiodev_open(); + else + radiodev_close(); + } + + return status; +} + +bool tuner_powered(void) +{ + return tuner_on; +} +#endif /* #if CONFIG_TUNER */ diff --git a/firmware/target/hosted/samsungypr/ypr1/system-ypr1.c b/firmware/target/hosted/samsungypr/ypr1/system-ypr1.c new file mode 100644 index 0000000000..d0cbddc55a --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/system-ypr1.c @@ -0,0 +1,67 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2013 Lorenzo Miori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include "system.h" +#include "panic.h" +#include "debug.h" + +#include "gpio-target.h" +#include "pmu-ypr1.h" +#include "ioctl-ypr1.h" +#include "audiohw.h" +#include "button-target.h" + +void power_off(void) +{ + /* Something that we need to do before exit on our platform */ + pmu_close(); + max17040_close(); + button_close_device(); + gpio_close(); + exit(EXIT_SUCCESS); +} + +uintptr_t *stackbegin; +uintptr_t *stackend; +void system_init(void) +{ + int *s; + /* fake stack, OS manages size (and growth) */ + stackbegin = stackend = (uintptr_t*)&s; + + /* Here begins our platform specific initilization for various things */ + audiohw_init(); + gpio_init(); + max17040_init(); + pmu_init(); +} + +void system_reboot(void) +{ + power_off(); +} + +void system_exception_wait(void) +{ + system_reboot(); +} diff --git a/firmware/target/hosted/samsungypr/ypr1/wmcodec-ypr1.c b/firmware/target/hosted/samsungypr/ypr1/wmcodec-ypr1.c new file mode 100644 index 0000000000..f38c33ada1 --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/wmcodec-ypr1.c @@ -0,0 +1,90 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * I2C bus wrapper for WM1808 codec on SAMSUNG YP-R1 + * + * Copyright (c) 2013 Lorenzo Miori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> + +#include "system.h" +#include "audiohw.h" +#include "wmcodec.h" +#include "audio.h" +#include "panic.h" +#include "logf.h" + + +#define I2C_SLAVE 0x0703 + +/** + * YP-R1's kernel has ALSA implementation of the WM1808, but it + * unfortunately doesn't export any function to play with register. + * For that reason we control the I2C bus directly, letting RB driver to do the rest + * Assumption: no other ALSA applications are using the mixer! + */ + +static int wmcodec_dev = -1; + +/* The ONLY tested freq for now is 44100, others are just stubs!! */ +const struct wmc_srctrl_entry wmc_srctrl_table[HW_NUM_FREQ] = +{ + /* TODO fix PLL frequencies also for the other available rates */ + [HW_FREQ_44] = /* PLL = on */ + { + .plln = 3 | (1 << 3), + .pllk1 = 0x18, /* 11289600 */ + .pllk2 = 0x111, + .pllk3 = 0x139, + .mclkdiv = WMC_MCLKDIV_2, + .filter = WMC_SR_48KHZ, + }, +}; + +void audiohw_init(void) +{ + /* First of all we need to open the device */ + wmcodec_dev = open("/dev/i2c-1", O_RDWR); + if (wmcodec_dev < 0) + panicf("Failed to open /dev/i2c-1 device!\n"); + + /* Let's set the slave address and if no error we are ready!*/ + int addr = 0x1a; + if (ioctl(wmcodec_dev, I2C_SLAVE, addr) < 0) + logf("Failed to set slave address!\n"); +} + +void wmcodec_write(int reg, int data) +{ + unsigned char data2[2]; + /* |aaaaaaad|dddddddd| */ + data2[0] = (reg << 0x1) | ((data >> 8) & 0x1); + data2[1] = data; + + if (write(wmcodec_dev, data2, 2) < 0) + panicf("I2C device write error!\n"); +} + +void audiohw_enable_headphone_jack(bool enable) +{ + /* We don't use this facility: we have a separate GPIO for that */ + (void)enable; +} diff --git a/firmware/target/hosted/samsungypr/ypr1/ypr1.make b/firmware/target/hosted/samsungypr/ypr1/ypr1.make new file mode 100644 index 0000000000..67ff326de0 --- /dev/null +++ b/firmware/target/hosted/samsungypr/ypr1/ypr1.make @@ -0,0 +1,24 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + +INCLUDES += -I$(FIRMDIR)/include -I$(FIRMDIR)/export $(TARGET_INC) -I$(BUILDDIR) -I$(APPSDIR) + +SIMFLAGS += $(INCLUDES) $(DEFINES) -DHAVE_CONFIG_H $(GCCOPTS) + +.SECONDEXPANSION: # $$(OBJ) is not populated until after this + +$(BUILDDIR)/rockbox.elf : $$(OBJ) $(FIRMLIB) $(VOICESPEEXLIB) $(CORE_LIBS) + $(call PRINTS,LD $(@F))$(CC) $(GCCOPTS) -Os -o $@ $(OBJ) \ + -L$(BUILDDIR)/firmware -lfirmware \ + -L$(RBCODEC_BLD)/codecs $(call a2lnk, $(VOICESPEEXLIB)) \ + -L$(BUILDDIR)/lib $(call a2lnk,$(CORE_LIBS)) \ + $(LDOPTS) $(GLOBAL_LDOPTS) -Wl,-Map,$(BUILDDIR)/rockbox.map + +$(BUILDDIR)/rockbox : $(BUILDDIR)/rockbox.elf + $(call PRINTS,OC $(@F))$(call objcopy,$^,$@) |