Commit | Line | Data |
---|---|---|
fb5103f9 PLB |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright(c) 2020 Intel Corporation. | |
3 | ||
4 | #include <linux/device.h> | |
5 | #include <linux/errno.h> | |
6 | #include <linux/module.h> | |
7 | #include <linux/regmap.h> | |
8 | #include <linux/soundwire/sdw.h> | |
9 | #include <linux/soundwire/sdw_registers.h> | |
10 | #include "internal.h" | |
11 | ||
12 | static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int val) | |
13 | { | |
14 | struct device *dev = context; | |
15 | struct sdw_slave *slave = dev_to_sdw_dev(dev); | |
16 | int ret; | |
17 | ||
4038e54b | 18 | ret = sdw_write_no_pm(slave, SDW_SDCA_MBQ_CTL(reg), (val >> 8) & 0xff); |
fb5103f9 PLB |
19 | if (ret < 0) |
20 | return ret; | |
21 | ||
4038e54b | 22 | return sdw_write_no_pm(slave, reg, val & 0xff); |
fb5103f9 PLB |
23 | } |
24 | ||
25 | static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *val) | |
26 | { | |
27 | struct device *dev = context; | |
28 | struct sdw_slave *slave = dev_to_sdw_dev(dev); | |
29 | int read0; | |
30 | int read1; | |
31 | ||
4038e54b | 32 | read0 = sdw_read_no_pm(slave, reg); |
fb5103f9 PLB |
33 | if (read0 < 0) |
34 | return read0; | |
35 | ||
4038e54b | 36 | read1 = sdw_read_no_pm(slave, SDW_SDCA_MBQ_CTL(reg)); |
fb5103f9 PLB |
37 | if (read1 < 0) |
38 | return read1; | |
39 | ||
40 | *val = (read1 << 8) | read0; | |
41 | ||
42 | return 0; | |
43 | } | |
44 | ||
bd941dfa | 45 | static const struct regmap_bus regmap_sdw_mbq = { |
fb5103f9 PLB |
46 | .reg_read = regmap_sdw_mbq_read, |
47 | .reg_write = regmap_sdw_mbq_write, | |
48 | .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, | |
49 | .val_format_endian_default = REGMAP_ENDIAN_LITTLE, | |
50 | }; | |
51 | ||
52 | static int regmap_sdw_mbq_config_check(const struct regmap_config *config) | |
53 | { | |
54 | /* MBQ-based controls are only 16-bits for now */ | |
55 | if (config->val_bits != 16) | |
56 | return -ENOTSUPP; | |
57 | ||
58 | /* Registers are 32 bits wide */ | |
59 | if (config->reg_bits != 32) | |
60 | return -ENOTSUPP; | |
61 | ||
62 | if (config->pad_bits != 0) | |
63 | return -ENOTSUPP; | |
64 | ||
65 | return 0; | |
66 | } | |
67 | ||
68 | struct regmap *__regmap_init_sdw_mbq(struct sdw_slave *sdw, | |
69 | const struct regmap_config *config, | |
70 | struct lock_class_key *lock_key, | |
71 | const char *lock_name) | |
72 | { | |
73 | int ret; | |
74 | ||
75 | ret = regmap_sdw_mbq_config_check(config); | |
76 | if (ret) | |
77 | return ERR_PTR(ret); | |
78 | ||
79 | return __regmap_init(&sdw->dev, ®map_sdw_mbq, | |
80 | &sdw->dev, config, lock_key, lock_name); | |
81 | } | |
82 | EXPORT_SYMBOL_GPL(__regmap_init_sdw_mbq); | |
83 | ||
84 | struct regmap *__devm_regmap_init_sdw_mbq(struct sdw_slave *sdw, | |
85 | const struct regmap_config *config, | |
86 | struct lock_class_key *lock_key, | |
87 | const char *lock_name) | |
88 | { | |
89 | int ret; | |
90 | ||
91 | ret = regmap_sdw_mbq_config_check(config); | |
92 | if (ret) | |
93 | return ERR_PTR(ret); | |
94 | ||
95 | return __devm_regmap_init(&sdw->dev, ®map_sdw_mbq, | |
96 | &sdw->dev, config, lock_key, lock_name); | |
97 | } | |
98 | EXPORT_SYMBOL_GPL(__devm_regmap_init_sdw_mbq); | |
99 | ||
c1ffff88 | 100 | MODULE_DESCRIPTION("regmap SoundWire MBQ Module"); |
8d8d9584 | 101 | MODULE_LICENSE("GPL"); |