soundwire: qcom: Fix build failure when slimbus is module
[linux-block.git] / drivers / soundwire / master.c
CommitLineData
7ceaa40b
PLB
1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright(c) 2019-2020 Intel Corporation.
3
4#include <linux/device.h>
5#include <linux/acpi.h>
26d97022 6#include <linux/pm_runtime.h>
7ceaa40b
PLB
7#include <linux/soundwire/sdw.h>
8#include <linux/soundwire/sdw_type.h>
9#include "bus.h"
10
c5778ca4
PLB
11/*
12 * The sysfs for properties reflects the MIPI description as given
13 * in the MIPI DisCo spec
14 *
15 * Base file is:
16 * sdw-master-N
17 * |---- revision
18 * |---- clk_stop_modes
19 * |---- max_clk_freq
20 * |---- clk_freq
21 * |---- clk_gears
22 * |---- default_row
23 * |---- default_col
24 * |---- dynamic_shape
25 * |---- err_threshold
26 */
27
28#define sdw_master_attr(field, format_string) \
29static ssize_t field##_show(struct device *dev, \
30 struct device_attribute *attr, \
31 char *buf) \
32{ \
33 struct sdw_master_device *md = dev_to_sdw_master_device(dev); \
34 return sprintf(buf, format_string, md->bus->prop.field); \
35} \
36static DEVICE_ATTR_RO(field)
37
38sdw_master_attr(revision, "0x%x\n");
39sdw_master_attr(clk_stop_modes, "0x%x\n");
40sdw_master_attr(max_clk_freq, "%d\n");
41sdw_master_attr(default_row, "%d\n");
42sdw_master_attr(default_col, "%d\n");
43sdw_master_attr(default_frame_rate, "%d\n");
44sdw_master_attr(dynamic_frame, "%d\n");
45sdw_master_attr(err_threshold, "%d\n");
46
47static ssize_t clock_frequencies_show(struct device *dev,
48 struct device_attribute *attr, char *buf)
49{
50 struct sdw_master_device *md = dev_to_sdw_master_device(dev);
51 ssize_t size = 0;
52 int i;
53
54 for (i = 0; i < md->bus->prop.num_clk_freq; i++)
55 size += sprintf(buf + size, "%8d ",
56 md->bus->prop.clk_freq[i]);
57 size += sprintf(buf + size, "\n");
58
59 return size;
60}
61static DEVICE_ATTR_RO(clock_frequencies);
62
63static ssize_t clock_gears_show(struct device *dev,
64 struct device_attribute *attr, char *buf)
65{
66 struct sdw_master_device *md = dev_to_sdw_master_device(dev);
67 ssize_t size = 0;
68 int i;
69
70 for (i = 0; i < md->bus->prop.num_clk_gears; i++)
71 size += sprintf(buf + size, "%8d ",
72 md->bus->prop.clk_gears[i]);
73 size += sprintf(buf + size, "\n");
74
75 return size;
76}
77static DEVICE_ATTR_RO(clock_gears);
78
79static struct attribute *master_node_attrs[] = {
80 &dev_attr_revision.attr,
81 &dev_attr_clk_stop_modes.attr,
82 &dev_attr_max_clk_freq.attr,
83 &dev_attr_default_row.attr,
84 &dev_attr_default_col.attr,
85 &dev_attr_default_frame_rate.attr,
86 &dev_attr_dynamic_frame.attr,
87 &dev_attr_err_threshold.attr,
88 &dev_attr_clock_frequencies.attr,
89 &dev_attr_clock_gears.attr,
90 NULL,
91};
92ATTRIBUTE_GROUPS(master_node);
93
7ceaa40b
PLB
94static void sdw_master_device_release(struct device *dev)
95{
96 struct sdw_master_device *md = dev_to_sdw_master_device(dev);
97
98 kfree(md);
99}
100
26d97022
BL
101static const struct dev_pm_ops master_dev_pm = {
102 SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend,
103 pm_generic_runtime_resume, NULL)
104};
105
7ceaa40b
PLB
106struct device_type sdw_master_type = {
107 .name = "soundwire_master",
108 .release = sdw_master_device_release,
26d97022 109 .pm = &master_dev_pm,
7ceaa40b
PLB
110};
111
112/**
113 * sdw_master_device_add() - create a Linux Master Device representation.
114 * @bus: SDW bus instance
115 * @parent: parent device
116 * @fwnode: firmware node handle
117 */
118int sdw_master_device_add(struct sdw_bus *bus, struct device *parent,
119 struct fwnode_handle *fwnode)
120{
121 struct sdw_master_device *md;
122 int ret;
123
124 if (!parent)
125 return -EINVAL;
126
127 md = kzalloc(sizeof(*md), GFP_KERNEL);
128 if (!md)
129 return -ENOMEM;
130
131 md->dev.bus = &sdw_bus_type;
132 md->dev.type = &sdw_master_type;
133 md->dev.parent = parent;
c5778ca4 134 md->dev.groups = master_node_groups;
7ceaa40b
PLB
135 md->dev.of_node = parent->of_node;
136 md->dev.fwnode = fwnode;
137 md->dev.dma_mask = parent->dma_mask;
138
139 dev_set_name(&md->dev, "sdw-master-%d", bus->id);
140
141 ret = device_register(&md->dev);
142 if (ret) {
143 dev_err(parent, "Failed to add master: ret %d\n", ret);
144 /*
145 * On err, don't free but drop ref as this will be freed
146 * when release method is invoked.
147 */
148 put_device(&md->dev);
149 goto device_register_err;
150 }
151
152 /* add shortcuts to improve code readability/compactness */
153 md->bus = bus;
154 bus->dev = &md->dev;
155 bus->md = md;
156
bd84256e 157 pm_runtime_enable(&bus->md->dev);
7ceaa40b
PLB
158device_register_err:
159 return ret;
160}
161
162/**
163 * sdw_master_device_del() - delete a Linux Master Device representation.
164 * @bus: bus handle
165 *
166 * This function is the dual of sdw_master_device_add()
167 */
168int sdw_master_device_del(struct sdw_bus *bus)
169{
bd84256e 170 pm_runtime_disable(&bus->md->dev);
7ceaa40b
PLB
171 device_unregister(bus->dev);
172
173 return 0;
174}