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
This commit is contained in:
Lorenzo Miori 2013-09-10 22:48:34 +02:00 committed by Thomas Martitz
parent b828b9d99b
commit e876f4df6d
36 changed files with 1849 additions and 48 deletions

View file

@ -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);
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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_ */

View file

@ -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 */

View file

@ -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 */

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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

View file

@ -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 */

View file

@ -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();
}

View file

@ -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;
}

View file

@ -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,$^,$@)