]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-pinebook-pro.patch
- up to 5.11.8
[packages/kernel.git] / kernel-pinebook-pro.patch
CommitLineData
8c9054af
JP
1From c223fa5f3cded17156fb781c1861a92349c4c5be Mon Sep 17 00:00:00 2001
2From: Tobias Schramm <t.schramm@manjaro.org>
3Date: Thu, 28 May 2020 14:01:59 +0200
4Subject: [PATCH] leds: Add support for inverted LED triggers
5
6Needs to be changed for upstream, invert via sysfs not trigger duplication
7
8Signed-off-by: Tobias Schramm <t.schramm@manjaro.org>
9---
10 drivers/leds/led-core.c | 1 +
11 drivers/leds/led-triggers.c | 149 +++++++++++++++++++++++++++---------
12 include/linux/leds.h | 1 +
13 3 files changed, 113 insertions(+), 38 deletions(-)
14
15diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
16index c4e780bdb385..3973676d6f1e 100644
17--- a/drivers/leds/led-core.c
18+++ b/drivers/leds/led-core.c
19@@ -177,6 +177,7 @@ static void led_blink_setup(struct led_classdev *led_cdev,
20 unsigned long *delay_off)
21 {
22 if (!test_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags) &&
23+ !test_bit(LED_BLINK_INVERT, &led_cdev->work_flags) &&
24 led_cdev->blink_set &&
25 !led_cdev->blink_set(led_cdev, delay_on, delay_off))
26 return;
27diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
28index 91da90cfb11d..7f2898a0e1e3 100644
29--- a/drivers/leds/led-triggers.c
30+++ b/drivers/leds/led-triggers.c
31@@ -27,20 +27,89 @@ LIST_HEAD(trigger_list);
32
33 /* Used by LED Class */
34
35+
36 static inline bool
37 trigger_relevant(struct led_classdev *led_cdev, struct led_trigger *trig)
38 {
39 return !trig->trigger_type || trig->trigger_type == led_cdev->trigger_type;
40 }
41
42+
43+#define TRIGGER_INVERT_SUFFIX "-inverted"
44+
45+/*
46+ * Check suffix of trigger name agains TRIGGER_INVERT_SUFFIX
47+ */
48+static bool led_trigger_is_inverted(const char *trigname)
49+{
50+ if (strlen(trigname) >= strlen(TRIGGER_INVERT_SUFFIX)) {
51+ return !strcmp(trigname + strlen(trigname) -
52+ strlen(TRIGGER_INVERT_SUFFIX),
53+ TRIGGER_INVERT_SUFFIX);
54+ }
55+
56+ return false;
57+}
58+
59+/*
60+ * Get length of trigger name name without TRIGGER_INVERT_SUFFIX
61+ */
62+static size_t led_trigger_get_name_len(const char *trigname)
63+{
64+ // Subtract length of TRIGGER_INVERT_SUFFIX if trigger is inverted
65+ if (led_trigger_is_inverted(trigname))
66+ return strlen(trigname) - strlen(TRIGGER_INVERT_SUFFIX);
67+ return strlen(trigname);
68+}
69+
70+/*
71+ * Find and set led trigger by name
72+ */
73+static int led_trigger_set_str_(struct led_classdev *led_cdev,
74+ const char *trigname, bool lock)
75+{
76+ struct led_trigger *trig;
77+ bool inverted = led_trigger_is_inverted(trigname);
78+ size_t len = led_trigger_get_name_len(trigname);
79+
80+ down_read(&triggers_list_lock);
81+ list_for_each_entry(trig, &trigger_list, next_trig) {
82+ /* Compare trigger name without inversion suffix */
83+ if (strlen(trig->name) == len &&
84+ !strncmp(trigname, trig->name, len) &&
85+ trigger_relevant(led_cdev, trig)) {
86+ if (lock)
87+ down_write(&led_cdev->trigger_lock);
88+ led_trigger_set(led_cdev, trig);
89+ if (inverted)
90+ led_cdev->flags |= LED_INVERT_TRIGGER;
91+ else
92+ led_cdev->flags &= ~LED_INVERT_TRIGGER;
93+ if (lock)
94+ up_write(&led_cdev->trigger_lock);
95+
96+ up_read(&triggers_list_lock);
97+ return 0;
98+ }
99+ }
100+ /* we come here only if trigname matches no trigger */
101+ up_read(&triggers_list_lock);
102+ return -EINVAL;
103+}
104+
105+#define led_trigger_set_str(cdev, name) led_trigger_set_str_(cdev, name, true)
106+#define led_trigger_set_str_unlocked(cdev, name) \
107+ led_trigger_set_str_(cdev, name, false)
108+
109+
110 ssize_t led_trigger_write(struct file *filp, struct kobject *kobj,
111 struct bin_attribute *bin_attr, char *buf,
112 loff_t pos, size_t count)
113 {
114 struct device *dev = kobj_to_dev(kobj);
115 struct led_classdev *led_cdev = dev_get_drvdata(dev);
116- struct led_trigger *trig;
117 int ret = count;
118+ char *name;
119
120 mutex_lock(&led_cdev->led_access);
121
122@@ -54,20 +123,10 @@ ssize_t led_trigger_write(struct file *filp, struct kobject *kobj,
123 goto unlock;
124 }
125
126- down_read(&triggers_list_lock);
127- list_for_each_entry(trig, &trigger_list, next_trig) {
128- if (sysfs_streq(buf, trig->name) && trigger_relevant(led_cdev, trig)) {
129- down_write(&led_cdev->trigger_lock);
130- led_trigger_set(led_cdev, trig);
131- up_write(&led_cdev->trigger_lock);
132-
133- up_read(&triggers_list_lock);
134- goto unlock;
135- }
136- }
137- /* we come here only if buf matches no trigger */
138- ret = -EINVAL;
139- up_read(&triggers_list_lock);
140+ name = strim(buf);
141+ ret = led_trigger_set_str(led_cdev, name);
142+ if (!ret)
143+ ret = count;
144
145 unlock:
146 mutex_unlock(&led_cdev->led_access);
147@@ -99,16 +158,25 @@ static int led_trigger_format(char *buf, size_t size,
148 led_cdev->trigger ? "none" : "[none]");
149
150 list_for_each_entry(trig, &trigger_list, next_trig) {
151- bool hit;
152+ bool hit = led_cdev->trigger == trig;
153+ bool inverted = led_cdev->flags & LED_INVERT_TRIGGER;
154
155 if (!trigger_relevant(led_cdev, trig))
156 continue;
157
158- hit = led_cdev->trigger && !strcmp(led_cdev->trigger->name, trig->name);
159+ /* print non-inverted trigger */
160+ len += led_trigger_snprintf(buf + len, size - len,
161+ " %s%s%s",
162+ hit && !inverted ? "[" : "",
163+ trig->name,
164+ hit && !inverted ? "]" : "");
165
166+ /* print inverted trigger */
167 len += led_trigger_snprintf(buf + len, size - len,
168- " %s%s%s", hit ? "[" : "",
169- trig->name, hit ? "]" : "");
170+ " %s%s"TRIGGER_INVERT_SUFFIX"%s",
171+ hit && inverted ? "[" : "",
172+ trig->name,
173+ hit && inverted ? "]" : "");
174 }
175
176 len += led_trigger_snprintf(buf + len, size - len, "\n");
177@@ -245,22 +313,15 @@ EXPORT_SYMBOL_GPL(led_trigger_remove);
178
179 void led_trigger_set_default(struct led_classdev *led_cdev)
180 {
181- struct led_trigger *trig;
182+ bool found;
183
184 if (!led_cdev->default_trigger)
185 return;
186
187 down_read(&triggers_list_lock);
188- down_write(&led_cdev->trigger_lock);
189- list_for_each_entry(trig, &trigger_list, next_trig) {
190- if (!strcmp(led_cdev->default_trigger, trig->name) &&
191- trigger_relevant(led_cdev, trig)) {
192- led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER;
193- led_trigger_set(led_cdev, trig);
194- break;
195- }
196- }
197- up_write(&led_cdev->trigger_lock);
198+ found = !led_trigger_set_str(led_cdev, led_cdev->default_trigger);
199+ if (found)
200+ led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER;
201 up_read(&triggers_list_lock);
202 }
203 EXPORT_SYMBOL_GPL(led_trigger_set_default);
204@@ -305,12 +366,15 @@ int led_trigger_register(struct led_trigger *trig)
205 /* Register with any LEDs that have this as a default trigger */
206 down_read(&leds_list_lock);
207 list_for_each_entry(led_cdev, &leds_list, node) {
208+ bool found;
209+
210 down_write(&led_cdev->trigger_lock);
211 if (!led_cdev->trigger && led_cdev->default_trigger &&
212- !strcmp(led_cdev->default_trigger, trig->name) &&
213 trigger_relevant(led_cdev, trig)) {
214- led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER;
215- led_trigger_set(led_cdev, trig);
216+ found = !led_trigger_set_str_unlocked(led_cdev,
217+ led_cdev->default_trigger);
218+ if (found)
219+ led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER;
220 }
221 up_write(&led_cdev->trigger_lock);
222 }
223@@ -383,8 +447,14 @@ void led_trigger_event(struct led_trigger *trig,
224 return;
225
226 read_lock_irqsave(&trig->leddev_list_lock, flags);
227- list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list)
228- led_set_brightness(led_cdev, brightness);
229+ list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) {
230+ /* Reverse brightness if LED is inverted */
231+ if (led_cdev->flags & LED_INVERT_TRIGGER)
232+ led_set_brightness(led_cdev,
233+ led_cdev->max_brightness - brightness);
234+ else
235+ led_set_brightness(led_cdev, brightness);
236+ }
237 read_unlock_irqrestore(&trig->leddev_list_lock, flags);
238 }
239 EXPORT_SYMBOL_GPL(led_trigger_event);
240@@ -402,10 +472,13 @@ static void led_trigger_blink_setup(struct led_trigger *trig,
241
242 read_lock(&trig->leddev_list_lock);
243 list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) {
244- if (oneshot)
245+ bool trigger_inverted =
246+ !!(led_cdev->flags & LED_INVERT_TRIGGER);
247+ if (oneshot) {
248+ /* use logical xnor to determine inversion parameter */
249 led_blink_set_oneshot(led_cdev, delay_on, delay_off,
250- invert);
251- else
252+ (!!invert) == trigger_inverted);
253+ } else
254 led_blink_set(led_cdev, delay_on, delay_off);
255 }
256 read_unlock(&trig->leddev_list_lock);
257diff --git a/include/linux/leds.h b/include/linux/leds.h
258index 6a8d6409c993..9cbf42cf08e8 100644
259--- a/include/linux/leds.h
260+++ b/include/linux/leds.h
261@@ -79,6 +79,7 @@ struct led_classdev {
262 #define LED_BRIGHT_HW_CHANGED BIT(21)
263 #define LED_RETAIN_AT_SHUTDOWN BIT(22)
264 #define LED_INIT_DEFAULT_TRIGGER BIT(23)
265+#define LED_INVERT_TRIGGER BIT(24)
266
267 /* set_brightness_work / blink_timer flags, atomic, private. */
268 unsigned long work_flags;
269--
270GitLab
271
272From 90a117ec260f54078aabcf2c1cde72f4425116ba Mon Sep 17 00:00:00 2001
273From: Tobias Schramm <t.schramm@manjaro.org>
274Date: Thu, 28 May 2020 14:12:56 +0200
275Subject: [PATCH] tty: serdev: support shutdown op
276
277Allow serdev drivers to register a shutdown handler
278
279Signed-off-by: Tobias Schramm <t.schramm@manjaro.org>
280---
281 drivers/tty/serdev/core.c | 11 +++++++++++
282 include/linux/serdev.h | 1 +
283 2 files changed, 12 insertions(+)
284
285diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
286index c5f0d936b003..37e45c356540 100644
287--- a/drivers/tty/serdev/core.c
288+++ b/drivers/tty/serdev/core.c
289@@ -432,11 +432,22 @@ static int serdev_drv_remove(struct device *dev)
290 return 0;
291 }
292
293+static void serdev_drv_shutdown(struct device *dev)
294+{
295+ const struct serdev_device_driver *sdrv;
296+ if (dev->driver) {
297+ sdrv = to_serdev_device_driver(dev->driver);
298+ if (sdrv->shutdown)
299+ sdrv->shutdown(to_serdev_device(dev));
300+ }
301+}
302+
303 static struct bus_type serdev_bus_type = {
304 .name = "serial",
305 .match = serdev_device_match,
306 .probe = serdev_drv_probe,
307 .remove = serdev_drv_remove,
308+ .shutdown = serdev_drv_shutdown,
309 };
310
311 /**
312diff --git a/include/linux/serdev.h b/include/linux/serdev.h
313index 9f14f9c12ec4..94050561325c 100644
314--- a/include/linux/serdev.h
315+++ b/include/linux/serdev.h
316@@ -63,6 +63,7 @@ struct serdev_device_driver {
317 struct device_driver driver;
318 int (*probe)(struct serdev_device *);
319 void (*remove)(struct serdev_device *);
320+ void (*shutdown)(struct serdev_device *);
321 };
322
323 static inline struct serdev_device_driver *to_serdev_device_driver(struct device_driver *d)
324--
325GitLab
326
327From 4381cb3400bd61288d2122f3eb74711963885323 Mon Sep 17 00:00:00 2001
328From: Tobias Schramm <t.schramm@manjaro.org>
329Date: Thu, 28 May 2020 14:14:06 +0200
330Subject: [PATCH] bluetooth: hci_serdev: Clear registered bit on unregister
331
332Signed-off-by: Tobias Schramm <t.schramm@manjaro.org>
333---
334 drivers/bluetooth/hci_serdev.c | 2 ++
335 1 file changed, 2 insertions(+)
336
337diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c
338index ef96ad06fa54..95c723c0ea01 100644
339--- a/drivers/bluetooth/hci_serdev.c
340+++ b/drivers/bluetooth/hci_serdev.c
341@@ -395,5 +395,7 @@ void hci_uart_unregister_device(struct hci_uart *hu)
342 clear_bit(HCI_UART_PROTO_READY, &hu->flags);
343 serdev_device_close(hu->serdev);
344 }
345+
346+ clear_bit(HCI_UART_REGISTERED, &hu->flags);
347 }
348 EXPORT_SYMBOL_GPL(hci_uart_unregister_device);
349--
350GitLab
351
352From 4065c5018d7d4fc7d6ea51056a954f23320688ca Mon Sep 17 00:00:00 2001
353From: Tobias Schramm <t.schramm@manjaro.org>
354Date: Thu, 28 May 2020 14:15:08 +0200
355Subject: [PATCH] bluetooth: hci_bcm: disable power on shutdown
356
357Firmware behaves wonky when not power cycled over reboots
358
359Signed-off-by: Tobias Schramm <t.schramm@manjaro.org>
360---
361 drivers/bluetooth/hci_bcm.c | 18 ++++++++++++++++++
362 1 file changed, 18 insertions(+)
363
364diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
365index 8ea5ca8d71d6..6d5871992f79 100644
366--- a/drivers/bluetooth/hci_bcm.c
367+++ b/drivers/bluetooth/hci_bcm.c
368@@ -1469,6 +1469,23 @@ static void bcm_serdev_remove(struct serdev_device *serdev)
369 hci_uart_unregister_device(&bcmdev->serdev_hu);
370 }
371
372+static void bcm_serdev_shutdown(struct serdev_device *serdev)
373+{
374+ struct bcm_device *bcmdev = serdev_device_get_drvdata(serdev);
375+
376+/*
377+ if (test_bit(HCI_UART_REGISTERED, &bcmdev->hu->flags)) {
378+ hci_uart_unregister_device(&bcmdev->serdev_hu);
379+ }
380+*/
381+ dev_info(bcmdev->dev, "Cutting power to bluetooth module\n");
382+ if (bcm_gpio_set_power(bcmdev, false)) {
383+ dev_err(bcmdev->dev, "Failed to power down\n");
384+ }
385+ usleep_range(500000, 1000000);
386+}
387+
388+
389 #ifdef CONFIG_OF
390 static struct bcm_device_data bcm4354_device_data = {
391 .no_early_set_baudrate = true,
392@@ -1494,6 +1511,7 @@ MODULE_DEVICE_TABLE(of, bcm_bluetooth_of_match);
393 static struct serdev_device_driver bcm_serdev_driver = {
394 .probe = bcm_serdev_probe,
395 .remove = bcm_serdev_remove,
396+ .shutdown = bcm_serdev_shutdown,
397 .driver = {
398 .name = "hci_uart_bcm",
399 .of_match_table = of_match_ptr(bcm_bluetooth_of_match),
400--
401GitLab
402
403From f6419edc62979c1e67202b5dc10abd7b22bdedcf Mon Sep 17 00:00:00 2001
404From: Tobias Schramm <t.schramm@manjaro.org>
405Date: Thu, 28 May 2020 14:16:52 +0200
406Subject: [PATCH] mmc: core: pwrseq_simple: disable mmc power on shutdown
407
408Fix for Broadcom SDIO WiFi modules. They misbehave if reinitialized
409without a power cycle.
410
411Signed-off-by: Tobias Schramm <t.schramm@manjaro.org>
412---
413 drivers/mmc/core/pwrseq_simple.c | 19 ++++++++++++++++---
414 1 file changed, 16 insertions(+), 3 deletions(-)
415
416diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
417index ea4d3670560e..38fe7e29aba6 100644
418--- a/drivers/mmc/core/pwrseq_simple.c
419+++ b/drivers/mmc/core/pwrseq_simple.c
420@@ -80,10 +80,8 @@ static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host)
421 msleep(pwrseq->post_power_on_delay_ms);
422 }
423
424-static void mmc_pwrseq_simple_power_off(struct mmc_host *host)
425+static void __mmc_pwrseq_simple_power_off(struct mmc_pwrseq_simple *pwrseq)
426 {
427- struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
428-
429 mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
430
431 if (pwrseq->power_off_delay_us)
432@@ -96,6 +94,12 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host)
433 }
434 }
435
436+static void mmc_pwrseq_simple_power_off(struct mmc_host *host)
437+{
438+ struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
439+ __mmc_pwrseq_simple_power_off(pwrseq);
440+}
441+
442 static const struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = {
443 .pre_power_on = mmc_pwrseq_simple_pre_power_on,
444 .post_power_on = mmc_pwrseq_simple_post_power_on,
445@@ -151,9 +155,18 @@ static int mmc_pwrseq_simple_remove(struct platform_device *pdev)
446 return 0;
447 }
448
449+static void mmc_pwrseq_simple_shutdown(struct platform_device *pdev)
450+{
451+ struct mmc_pwrseq_simple *pwrseq = platform_get_drvdata(pdev);
452+
453+ dev_info(&pdev->dev, "Turning off mmc\n");
454+ __mmc_pwrseq_simple_power_off(pwrseq);
455+}
456+
457 static struct platform_driver mmc_pwrseq_simple_driver = {
458 .probe = mmc_pwrseq_simple_probe,
459 .remove = mmc_pwrseq_simple_remove,
460+ .shutdown = mmc_pwrseq_simple_shutdown,
461 .driver = {
462 .name = "pwrseq_simple",
463 .of_match_table = mmc_pwrseq_simple_of_match,
464--
465GitLab
466
467From b0452434e75ecf257bc2ea9a5eb86be68bb56f71 Mon Sep 17 00:00:00 2001
468From: Tobias Schramm <t.schramm@manjaro.org>
469Date: Thu, 28 May 2020 14:23:54 +0200
470Subject: [PATCH] usb: typec: tcpm: add hacky generic altmode support
471
472This is a hack and it is based on extcon. Do not try to mainline
473unless you are in need for some retroactive abortion by the
474maintainers.
475
476Signed-off-by: Tobias Schramm <t.schramm@manjaro.org>
477---
478 drivers/usb/typec/tcpm/tcpm.c | 139 +++++++++++++++++++++++++++++++++-
479 1 file changed, 138 insertions(+), 1 deletion(-)
480
481diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
482index a6fae1f86505..2908771f4d4e 100644
483--- a/drivers/usb/typec/tcpm/tcpm.c
484+++ b/drivers/usb/typec/tcpm/tcpm.c
485@@ -9,6 +9,7 @@
486 #include <linux/debugfs.h>
487 #include <linux/device.h>
488 #include <linux/hrtimer.h>
489+#include <linux/extcon-provider.h>
490 #include <linux/jiffies.h>
491 #include <linux/kernel.h>
492 #include <linux/kthread.h>
493@@ -369,6 +370,11 @@ struct tcpm_port {
494 /* Sink caps have been queried */
495 bool sink_cap_done;
496
497+#ifdef CONFIG_EXTCON
498+ struct extcon_dev *extcon;
499+ unsigned int *extcon_cables;
500+#endif
501+
502 #ifdef CONFIG_DEBUG_FS
503 struct dentry *dentry;
504 struct mutex logbuffer_lock; /* log buffer access lock */
505@@ -654,6 +660,35 @@ static void tcpm_debugfs_exit(const struct tcpm_port *port) { }
506
507 #endif
508
509+static void tcpm_update_extcon_data(struct tcpm_port *port, bool attached) {
510+#ifdef CONFIG_EXTCON
511+ unsigned int *capability = port->extcon_cables;
512+ if (port->data_role == TYPEC_HOST) {
513+ extcon_set_state(port->extcon, EXTCON_USB, false);
514+ extcon_set_state(port->extcon, EXTCON_USB_HOST, attached);
515+ } else {
516+ extcon_set_state(port->extcon, EXTCON_USB, true);
517+ extcon_set_state(port->extcon, EXTCON_USB_HOST, attached);
518+ }
519+ while (*capability != EXTCON_NONE) {
520+ if (attached) {
521+ union extcon_property_value val;
522+ val.intval = (port->polarity == TYPEC_POLARITY_CC2);
523+ extcon_set_property(port->extcon, *capability,
524+ EXTCON_PROP_USB_TYPEC_POLARITY, val);
525+ } else {
526+ extcon_set_state(port->extcon, *capability, false);
527+ }
528+ extcon_sync(port->extcon, *capability);
529+ capability++;
530+ }
531+ tcpm_log(port, "Extcon update (%s): %s, %s",
532+ attached ? "attached" : "detached",
533+ port->data_role == TYPEC_HOST ? "host" : "device",
534+ port->polarity == TYPEC_POLARITY_CC1 ? "normal" : "flipped");
535+#endif
536+}
537+
538 static int tcpm_pd_transmit(struct tcpm_port *port,
539 enum tcpm_transmit_type type,
540 const struct pd_message *msg)
541@@ -881,6 +916,8 @@ static int tcpm_set_roles(struct tcpm_port *port, bool attached,
542 typec_set_data_role(port->typec_port, data);
543 typec_set_pwr_role(port->typec_port, role);
544
545+ tcpm_update_extcon_data(port, attached);
546+
547 return 0;
548 }
549
550@@ -1132,7 +1169,7 @@ static void svdm_consume_modes(struct tcpm_port *port, const u32 *p, int cnt)
551 paltmode->mode = i;
552 paltmode->vdo = p[i];
553
554- tcpm_log(port, " Alternate mode %d: SVID 0x%04x, VDO %d: 0x%08x",
555+ tcpm_log(port, "Alternate mode %d: SVID 0x%04x, VDO %d: 0x%08x",
556 pmdata->altmodes, paltmode->svid,
557 paltmode->mode, paltmode->vdo);
558
559@@ -1154,6 +1191,9 @@ static void tcpm_register_partner_altmodes(struct tcpm_port *port)
560 modep->altmode_desc[i].svid);
561 altmode = NULL;
562 }
563+ else
564+ tcpm_log(port, "Registered altmode 0x%04x", modep->altmode_desc[i].svid);
565+
566 port->partner_altmode[i] = altmode;
567 }
568 }
569@@ -1249,9 +1289,11 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
570 modep->svid_index++;
571 if (modep->svid_index < modep->nsvids) {
572 u16 svid = modep->svids[modep->svid_index];
573+ tcpm_log(port, "More modes available, sending discover");
574 response[0] = VDO(svid, 1, CMD_DISCOVER_MODES);
575 rlen = 1;
576 } else {
577+ tcpm_log(port, "Got all patner modes, registering");
578 tcpm_register_partner_altmodes(port);
579 }
580 break;
581@@ -2836,6 +2878,7 @@ static int tcpm_src_attach(struct tcpm_port *port)
582 static void tcpm_typec_disconnect(struct tcpm_port *port)
583 {
584 if (port->connected) {
585+ tcpm_update_extcon_data(port, false);
586 typec_unregister_partner(port->partner);
587 port->partner = NULL;
588 port->connected = false;
589@@ -2902,6 +2945,8 @@ static void tcpm_detach(struct tcpm_port *port)
590 }
591
592 tcpm_reset_port(port);
593+
594+ tcpm_update_extcon_data(port, false);
595 }
596
597 static void tcpm_src_detach(struct tcpm_port *port)
598@@ -4732,6 +4777,64 @@ void tcpm_tcpc_reset(struct tcpm_port *port)
599 }
600 EXPORT_SYMBOL_GPL(tcpm_tcpc_reset);
601
602+unsigned int default_supported_cables[] = {
603+ EXTCON_NONE
604+};
605+
606+static int tcpm_fw_get_caps_late(struct tcpm_port *port,
607+ struct fwnode_handle *fwnode)
608+{
609+ int ret, i;
610+ ret = fwnode_property_count_u32(fwnode, "typec-altmodes");
611+ if (ret > 0) {
612+ u32 *props;
613+ if (ret % 4) {
614+ dev_err(port->dev, "Length of typec altmode array must be divisible by 4");
615+ return -EINVAL;
616+ }
617+
618+ props = devm_kzalloc(port->dev, sizeof(u32) * ret, GFP_KERNEL);
619+ if (!props) {
620+ dev_err(port->dev, "Failed to allocate memory for altmode properties");
621+ return -ENOMEM;
622+ }
623+
624+ if(fwnode_property_read_u32_array(fwnode, "typec-altmodes", props, ret) < 0) {
625+ dev_err(port->dev, "Failed to read altmodes from port");
626+ return -EINVAL;
627+ }
628+
629+ i = 0;
630+ while (ret > 0 && i < ARRAY_SIZE(port->port_altmode)) {
631+ struct typec_altmode *alt;
632+ struct typec_altmode_desc alt_desc = {
633+ .svid = props[i * 4],
634+ .mode = props[i * 4 + 1],
635+ .vdo = props[i * 4 + 2],
636+ .roles = props[i * 4 + 3],
637+ };
638+
639+
640+ tcpm_log(port, "Adding altmode SVID: 0x%04x, mode: %d, vdo: %u, role: %d",
641+ alt_desc.svid, alt_desc.mode, alt_desc.vdo, alt_desc.roles);
642+ alt = typec_port_register_altmode(port->typec_port,
643+ &alt_desc);
644+ if (IS_ERR(alt)) {
645+ tcpm_log(port,
646+ "%s: failed to register port alternate mode 0x%x",
647+ dev_name(port->dev), alt_desc.svid);
648+ break;
649+ }
650+ typec_altmode_set_drvdata(alt, port);
651+ alt->ops = &tcpm_altmode_ops;
652+ port->port_altmode[i] = alt;
653+ i++;
654+ ret -= 4;
655+ }
656+ }
657+ return 0;
658+}
659+
660 static int tcpm_fw_get_caps(struct tcpm_port *port,
661 struct fwnode_handle *fwnode)
662 {
663@@ -4742,6 +4845,23 @@ static int tcpm_fw_get_caps(struct tcpm_port *port,
664 if (!fwnode)
665 return -EINVAL;
666
667+#ifdef CONFIG_EXTCON
668+ ret = fwnode_property_count_u32(fwnode, "extcon-cables");
669+ if (ret > 0) {
670+ port->extcon_cables = devm_kzalloc(port->dev, sizeof(u32) * ret, GFP_KERNEL);
671+ if (!port->extcon_cables) {
672+ dev_err(port->dev, "Failed to allocate memory for extcon cable types. "\
673+ "Using default tyes");
674+ goto extcon_default;
675+ }
676+ fwnode_property_read_u32_array(fwnode, "extcon-cables", port->extcon_cables, ret);
677+ } else {
678+extcon_default:
679+ dev_info(port->dev, "No cable types defined, using default cables");
680+ port->extcon_cables = default_supported_cables;
681+ }
682+#endif
683+
684 /* USB data support is optional */
685 ret = fwnode_property_read_string(fwnode, "data-role", &cap_str);
686 if (ret == 0) {
687@@ -5114,6 +5234,17 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
688 goto out_destroy_wq;
689
690 port->try_role = port->typec_caps.prefer_role;
691+#ifdef CONFIG_EXTCON
692+ port->extcon = devm_extcon_dev_allocate(dev, port->extcon_cables);
693+ if (IS_ERR(port->extcon)) {
694+ dev_err(dev, "Failed to allocate extcon device: %ld", PTR_ERR(port->extcon));
695+ goto out_destroy_wq;
696+ }
697+ if((err = devm_extcon_dev_register(dev, port->extcon))) {
698+ dev_err(dev, "Failed to register extcon device: %d", err);
699+ goto out_destroy_wq;
700+ }
701+#endif
702
703 port->typec_caps.fwnode = tcpc->fwnode;
704 port->typec_caps.revision = 0x0120; /* Type-C spec release 1.2 */
705@@ -5141,6 +5272,12 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
706 goto out_role_sw_put;
707 }
708
709+ err = tcpm_fw_get_caps_late(port, tcpc->fwnode);
710+ if (err < 0) {
711+ dev_err(dev, "Failed to get altmodes from fwnode");
712+ goto out_destroy_wq;
713+ }
714+
715 mutex_lock(&port->lock);
716 tcpm_init(port);
717 mutex_unlock(&port->lock);
718--
719GitLab
720
721From db4e9ffdb985752ae3c3436ff86f8f376ae8fd22 Mon Sep 17 00:00:00 2001
722From: Tobias Schramm <t.schramm@manjaro.org>
723Date: Thu, 28 May 2020 14:25:32 +0200
724Subject: [PATCH] phy: rockchip: typec: Set extcon capabilities
725
726Do not mainline, hack.
727
728Signed-off-by: Tobias Schramm <t.schramm@manjaro.org>
729---
730 drivers/phy/rockchip/phy-rockchip-typec.c | 17 +++++++++++++++++
731 1 file changed, 17 insertions(+)
732
733diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
734index 70a31251b202..5385bb4f0bd4 100644
735--- a/drivers/phy/rockchip/phy-rockchip-typec.c
736+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
737@@ -40,6 +40,7 @@
738 #include <linux/clk-provider.h>
739 #include <linux/delay.h>
740 #include <linux/extcon.h>
741+#include <linux/extcon-provider.h>
742 #include <linux/io.h>
743 #include <linux/iopoll.h>
744 #include <linux/kernel.h>
745@@ -1160,6 +1161,22 @@ static int rockchip_typec_phy_probe(struct platform_device *pdev)
746 dev_err(dev, "Invalid or missing extcon\n");
747 return PTR_ERR(tcphy->extcon);
748 }
749+ } else {
750+ extcon_set_property_capability(tcphy->extcon, EXTCON_USB,
751+ EXTCON_PROP_USB_SS);
752+ extcon_set_property_capability(tcphy->extcon, EXTCON_USB_HOST,
753+ EXTCON_PROP_USB_SS);
754+ extcon_set_property_capability(tcphy->extcon, EXTCON_DISP_DP,
755+ EXTCON_PROP_USB_SS);
756+ extcon_set_property_capability(tcphy->extcon, EXTCON_USB,
757+ EXTCON_PROP_USB_TYPEC_POLARITY);
758+ extcon_set_property_capability(tcphy->extcon, EXTCON_USB_HOST,
759+ EXTCON_PROP_USB_TYPEC_POLARITY);
760+ extcon_set_property_capability(tcphy->extcon, EXTCON_DISP_DP,
761+ EXTCON_PROP_USB_TYPEC_POLARITY);
762+ extcon_sync(tcphy->extcon, EXTCON_USB);
763+ extcon_sync(tcphy->extcon, EXTCON_USB_HOST);
764+ extcon_sync(tcphy->extcon, EXTCON_DISP_DP);
765 }
766
767 pm_runtime_enable(dev);
768--
769GitLab
770
771From fd739ae47f9ea780a1e161a478e241df06eaff7e Mon Sep 17 00:00:00 2001
772From: Tobias Schramm <t.schramm@manjaro.org>
773Date: Thu, 28 May 2020 14:26:27 +0200
774Subject: [PATCH] usb: typec: altmodes: displayport: Add hacky, generic altmode
775 detection
776
777Do not mainline, hack.
778
779Signed-off-by: Tobias Schramm <t.schramm@manjaro.org>
780---
781 drivers/usb/typec/altmodes/displayport.c | 55 ++++++++++++++++++++++--
782 1 file changed, 52 insertions(+), 3 deletions(-)
783
784diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
785index e62e5e3da01e..a3d03db476aa 100644
786--- a/drivers/usb/typec/altmodes/displayport.c
787+++ b/drivers/usb/typec/altmodes/displayport.c
788@@ -9,6 +9,8 @@
789 */
790
791 #include <linux/delay.h>
792+#include <linux/extcon.h>
793+#include <linux/extcon-provider.h>
794 #include <linux/mutex.h>
795 #include <linux/module.h>
796 #include <linux/usb/pd_vdo.h>
797@@ -135,15 +137,53 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
798 return ret;
799 }
800
801+static void dp_altmode_update_extcon(struct dp_altmode *dp, bool disconnect) {
802+ const struct device *dev = &dp->port->dev;
803+ struct extcon_dev* edev = NULL;
804+
805+ while (dev) {
806+ edev = extcon_find_edev_by_node(dev->of_node);
807+ if(!IS_ERR(edev)) {
808+ break;
809+ }
810+ dev = dev->parent;
811+ }
812+
813+ if (IS_ERR_OR_NULL(edev)) {
814+ return;
815+ }
816+
817+ if (disconnect || !dp->data.conf) {
818+ extcon_set_state_sync(edev, EXTCON_DISP_DP, false);
819+ } else {
820+ union extcon_property_value extcon_true = { .intval = true };
821+ extcon_set_state(edev, EXTCON_DISP_DP, true);
822+ if (DP_CONF_GET_PIN_ASSIGN(dp->data.conf) & DP_PIN_ASSIGN_MULTI_FUNC_MASK) {
823+ extcon_set_state_sync(edev, EXTCON_USB_HOST, true);
824+ extcon_set_property(edev, EXTCON_DISP_DP, EXTCON_PROP_USB_SS,
825+ extcon_true);
826+ } else {
827+ extcon_set_state_sync(edev, EXTCON_USB_HOST, false);
828+ }
829+ extcon_sync(edev, EXTCON_DISP_DP);
830+ extcon_set_state_sync(edev, EXTCON_USB, false);
831+ }
832+
833+}
834+
835 static int dp_altmode_configured(struct dp_altmode *dp)
836 {
837 int ret;
838
839 sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration");
840
841- if (!dp->data.conf)
842+ if (!dp->data.conf) {
843+ dp_altmode_update_extcon(dp, true);
844 return typec_altmode_notify(dp->alt, TYPEC_STATE_USB,
845 &dp->data);
846+ }
847+
848+ dp_altmode_update_extcon(dp, false);
849
850 ret = dp_altmode_notify(dp);
851 if (ret)
852@@ -170,9 +210,11 @@ static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf)
853 if (ret) {
854 if (DP_CONF_GET_PIN_ASSIGN(dp->data.conf))
855 dp_altmode_notify(dp);
856- else
857+ else {
858+ dp_altmode_update_extcon(dp, true);
859 typec_altmode_notify(dp->alt, TYPEC_STATE_USB,
860 &dp->data);
861+ }
862 }
863
864 return ret;
865@@ -211,6 +253,8 @@ static void dp_altmode_work(struct work_struct *work)
866 case DP_STATE_EXIT:
867 if (typec_altmode_exit(dp->alt))
868 dev_err(&dp->alt->dev, "Exit Mode Failed!\n");
869+ else
870+ dp_altmode_update_extcon(dp, true);
871 break;
872 default:
873 break;
874@@ -521,8 +565,13 @@ int dp_altmode_probe(struct typec_altmode *alt)
875 if (!(DP_CAP_DFP_D_PIN_ASSIGN(port->vdo) &
876 DP_CAP_UFP_D_PIN_ASSIGN(alt->vdo)) &&
877 !(DP_CAP_UFP_D_PIN_ASSIGN(port->vdo) &
878- DP_CAP_DFP_D_PIN_ASSIGN(alt->vdo)))
879+ DP_CAP_DFP_D_PIN_ASSIGN(alt->vdo))) {
880+ dev_err(&alt->dev, "No compatible pin configuration found:"\
881+ "%04lx -> %04lx, %04lx <- %04lx",
882+ DP_CAP_DFP_D_PIN_ASSIGN(port->vdo), DP_CAP_UFP_D_PIN_ASSIGN(alt->vdo),
883+ DP_CAP_UFP_D_PIN_ASSIGN(port->vdo), DP_CAP_DFP_D_PIN_ASSIGN(alt->vdo));
884 return -ENODEV;
885+ }
886
887 ret = sysfs_create_group(&alt->dev.kobj, &dp_altmode_group);
888 if (ret)
889--
890GitLab
891
892From e9d07cf5d983a3b941e604ae4ba9d277929e0650 Mon Sep 17 00:00:00 2001
893From: Tobias Schramm <t.schramm@manjaro.org>
894Date: Thu, 28 May 2020 14:34:47 +0200
895Subject: [PATCH] sound: soc: codecs: es8316: Run micdetect only if jack status
896 asserted
897
898Think this is (was?) required to prevent flapping of detection status on
899the PBP.
900
901Signed-off-by: Tobias Schramm <t.schramm@manjaro.org>
902---
903 sound/soc/codecs/es8316.c | 2 +-
904 1 file changed, 1 insertion(+), 1 deletion(-)
905
906diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
907index bd5d230c5df2..a2d8bf620b6f 100644
908--- a/sound/soc/codecs/es8316.c
909+++ b/sound/soc/codecs/es8316.c
910@@ -688,7 +688,7 @@ static void es8316_disable_jack_detect(struct snd_soc_component *component)
911 snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE,
912 ES8316_GPIO_ENABLE_INTERRUPT, 0);
913
914- if (es8316->jack->status & SND_JACK_MICROPHONE) {
915+ if (es8316->jack && (es8316->jack->status & SND_JACK_MICROPHONE)) {
916 es8316_disable_micbias_for_mic_gnd_short_detect(component);
917 snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0);
918 }
919--
920GitLab
921
922From edbf5d93dbd845faa4aa74fb8a7c5e76cf35ef0d Mon Sep 17 00:00:00 2001
923From: Tobias Schramm <t.schramm@manjaro.org>
924Date: Thu, 28 May 2020 14:36:47 +0200
925Subject: [PATCH] ASoC: soc-jack.c: supported inverted jack detect GPIOs
926
927Signed-off-by: Tobias Schramm <t.schramm@manjaro.org>
928---
929 sound/soc/soc-jack.c | 7 ++++---
930 1 file changed, 4 insertions(+), 3 deletions(-)
931
932diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
933index 0f1820f36b4d..8d9d77814f33 100644
934--- a/sound/soc/soc-jack.c
935+++ b/sound/soc/soc-jack.c
936@@ -216,8 +216,6 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
937 int report;
938
939 enable = gpiod_get_value_cansleep(gpio->desc);
940- if (gpio->invert)
941- enable = !enable;
942
943 if (enable)
944 report = gpio->report;
945@@ -346,6 +344,9 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
946 goto undo;
947 }
948 } else {
949+ int flags = GPIOF_IN;
950+ if (gpios[i].invert)
951+ flags |= GPIOF_ACTIVE_LOW;
952 /* legacy GPIO number */
953 if (!gpio_is_valid(gpios[i].gpio)) {
954 dev_err(jack->card->dev,
955@@ -355,7 +356,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
956 goto undo;
957 }
958
959- ret = gpio_request_one(gpios[i].gpio, GPIOF_IN,
960+ ret = gpio_request_one(gpios[i].gpio, flags,
961 gpios[i].name);
962 if (ret)
963 goto undo;
964--
965GitLab
966
967From 43756ac8a7e63935843e95471a9557677cedcbe0 Mon Sep 17 00:00:00 2001
968From: Tobias Schramm <t.schramm@manjaro.org>
969Date: Thu, 28 May 2020 14:43:27 +0200
970Subject: [PATCH] arm64: dts: rockchip: add oficially unsupported 2GHz opp
971
972No mainlining here.
973
974Signed-off-by: Tobias Schramm <t.schramm@manjaro.org>
975---
976 arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts | 7 +++++++
977 1 file changed, 7 insertions(+)
978
979diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
980index 667eeeb019de..decb212e2dca 100644
981--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
982+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
983@@ -392,6 +392,13 @@ mains_charger: dc-charger {
984 };
985 };
986
987+&cluster1_opp {
988+ opp08 {
989+ opp-hz = /bits/ 64 <2016000000>;
990+ opp-microvolt = <1250000>;
991+ };
992+};
993+
994 &cdn_dp {
995 status = "okay";
996 };
997--
998GitLab
999
1000From 948d7ade0ddcf292b91d91cb8b6819a19ab3f604 Mon Sep 17 00:00:00 2001
1001From: Tobias Schramm <t.schramm@manjaro.org>
1002Date: Thu, 28 May 2020 14:44:15 +0200
1003Subject: [PATCH] arm64: dts: rockchip: add typec extcon hack
1004
1005Not for mainline
1006
1007Signed-off-by: Tobias Schramm <t.schramm@manjaro.org>
1008---
1009 arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts | 5 +++++
1010 1 file changed, 5 insertions(+)
1011
1012diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
1013index decb212e2dca..37f967a89401 100644
1014--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
1015+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
1016@@ -401,6 +401,7 @@ opp08 {
1017
1018 &cdn_dp {
1019 status = "okay";
1020+ extcon = <&fusb0>;
1021 };
1022
1023 &cpu_b0 {
1024@@ -735,6 +736,9 @@ connector {
1025 <PDO_FIXED(5000, 1400, PDO_FIXED_USB_COMM)>;
1026 try-power-role = "sink";
1027
1028+ extcon-cables = <1 2 5 6 9 10 12 44>;
1029+ typec-altmodes = <0xff01 1 0x001c0000 1>;
1030+
1031 ports {
1032 #address-cells = <1>;
1033 #size-cells = <0>;
1034@@ -1002,6 +1006,7 @@ spiflash: flash@0 {
1035 };
1036
1037 &tcphy0 {
1038+ extcon = <&fusb0>;
1039 status = "okay";
1040 };
1041
1042--
1043GitLab
1044
1045From a8f3e4ffe533f952a468cb8f3d067865bd58144f Mon Sep 17 00:00:00 2001
1046From: Tobias Schramm <t.schramm@manjaro.org>
1047Date: Sat, 6 Jun 2020 23:45:10 +0200
1048Subject: [PATCH] arm64: dts: rockchip: setup USB type c port as dual data role
1049
1050Some chargers try to put the charged device into device data role.
1051Before this commit this condition caused the tcpm state machine to
1052issue a hard reset due to a capability missmatch.
1053
1054Signed-off-by: Tobias Schramm <t.schramm@manjaro.org>
1055---
1056 arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts | 2 +-
1057 1 file changed, 1 insertion(+), 1 deletion(-)
1058
1059diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
1060index c505c88b5d9b..d77dca5524ff 100644
1061--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
1062+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
1063@@ -726,7 +726,7 @@ fusb0: fusb30x@22 {
1064
1065 connector {
1066 compatible = "usb-c-connector";
1067- data-role = "host";
1068+ data-role = "dual";
1069 label = "USB-C";
1070 op-sink-microwatt = <1000000>;
1071 power-role = "dual";
1072--
1073GitLab
1074
This page took 0.177925 seconds and 4 git commands to generate.