summaryrefslogtreecommitdiffstats
path: root/firmware/target/hosted/ypr0/ascodec-ypr0.c
blob: 954b4d95efc2d078cd545d4a4c47876cb0058342 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 *
 * Module wrapper for AS3543 audio codec, using /dev/afe (afe.ko) of Samsung YP-R0
 *
 * Copyright (c) 2011 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 "fcntl.h"
#include "unistd.h"
#include "stdio.h"
#include "string.h"
#include "sys/ioctl.h"
#include "stdlib.h"

#include "ascodec.h"

int afe_dev = -1;

/* ioctl parameter struct */
struct codec_req_struct {
/* This works for every kind of afe.ko module requests */
    unsigned char reg; /* Main register address */
    unsigned char subreg; /* Set this only if you are reading/writing a PMU register*/
    unsigned char value; /* To be read if reading a register; to be set if writing to a register */
} __attribute__((packed));


/* Write to a normal register */
#define IOCTL_REG_WRITE         0x40034101
/* Write to a PMU register */
#define IOCTL_SUBREG_WRITE      0x40034103
/* Read from a normal register */
#define IOCTL_REG_READ          0x80034102
/* Read from a PMU register */
#define IOCTL_SUBREG_READ       0x80034103


int ascodec_init(void)
{
    afe_dev = open("/dev/afe", O_RDWR);
    return afe_dev;
}

void ascodec_close(void)
{
    if (afe_dev >= 0) {
        close(afe_dev);
    }
}

/* Read functions returns -1 if fail, otherwise the register's value if success */
/* Write functions return >= 0 if success, otherwise -1 if fail */

int ascodec_write(unsigned int reg, unsigned int value)
{
    struct codec_req_struct r = { .reg = reg, .value = value };
    return ioctl(afe_dev, IOCTL_REG_WRITE, &r);
}

int ascodec_read(unsigned int reg)
{
    struct codec_req_struct r = { .reg = reg };
    int retval = ioctl(afe_dev, IOCTL_REG_READ, &r);
    if (retval >= 0)
        return r.value;
    else
        return retval;
}

void ascodec_write_pmu(unsigned int index, unsigned int subreg,
                                     unsigned int value)
{
    struct codec_req_struct r = {.reg = index, .subreg = subreg, .value = value};
    ioctl(afe_dev, IOCTL_SUBREG_WRITE, &r);
}

int ascodec_read_pmu(unsigned int index, unsigned int subreg)
{
    struct codec_req_struct r = { .reg = index, .subreg = subreg, };
    int retval = ioctl(afe_dev, IOCTL_SUBREG_READ, &r);
    if (retval >= 0)
        return r.value;
    else
        return retval;
}

int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data)
{
    int i, val, ret = 0;

    for (i = 0; i < (int)len; i++)
    {
        val = ascodec_read(i + index);
        if (val >= 0) data[i] = val;
        else ret = -1;
    }

    return (ret ?: (int)len);
}

/*
 * NOTE:
 * After the conversion to interrupts, ascodec_(lock|unlock) are only used by
 * adc-as3514.c to protect against other threads corrupting the result by using
 * the ADC at the same time. this adc_read() doesn't yield but blocks, so
 * lock/unlock is not needed
 * 
 * Additionally, concurrent ascodec_?(read|write) calls are instead protected
 * by the R0's Kernel I2C driver for ascodec (mutexed), so it's automatically
 * safe
 */

void ascodec_lock(void)
{
}

void ascodec_unlock(void)
{
}

bool ascodec_chg_status(void)
{
    return ascodec_read(AS3514_IRQ_ENRD0) & CHG_STATUS;
}   

bool ascodec_endofch(void)
{
    return ascodec_read(AS3514_IRQ_ENRD0) & CHG_ENDOFCH;
}

void ascodec_monitor_endofch(void)
{
    ascodec_write(AS3514_IRQ_ENRD0, IRQ_ENDOFCH);
}


void ascodec_write_charger(int value)
{
    ascodec_write_pmu(AS3543_CHARGER, 1, value);
}

int ascodec_read_charger(void)
{
    return ascodec_read_pmu(AS3543_CHARGER, 1);
}

void ascodec_wait_adc_finished(void)
{
}