xref: /dragonfly/sys/dev/drm/amd/display/dc/gpio/gpio_service.c (revision b843c749addef9340ee7d4e250b09fdd492602a1)
1 /*
2  * Copyright 2012-15 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: AMD
23  *
24  */
25 
26 /*
27  * Pre-requisites: headers required by header of this unit
28  */
29 
30 #include "dm_services.h"
31 #include "include/gpio_interface.h"
32 #include "include/gpio_service_interface.h"
33 #include "hw_translate.h"
34 #include "hw_factory.h"
35 
36 /*
37  * Header of this unit
38  */
39 
40 #include "gpio_service.h"
41 
42 /*
43  * Post-requisites: headers required by this unit
44  */
45 
46 #include "hw_gpio.h"
47 
48 /*
49  * @brief
50  * Public API.
51  */
52 
dal_gpio_service_create(enum dce_version dce_version_major,enum dce_version dce_version_minor,struct dc_context * ctx)53 struct gpio_service *dal_gpio_service_create(
54           enum dce_version dce_version_major,
55           enum dce_version dce_version_minor,
56           struct dc_context *ctx)
57 {
58           struct gpio_service *service;
59 
60           uint32_t index_of_id;
61 
62           service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL);
63 
64           if (!service) {
65                     BREAK_TO_DEBUGGER();
66                     return NULL;
67           }
68 
69           if (!dal_hw_translate_init(&service->translate, dce_version_major,
70                               dce_version_minor)) {
71                     BREAK_TO_DEBUGGER();
72                     goto failure_1;
73           }
74 
75           if (!dal_hw_factory_init(&service->factory, dce_version_major,
76                               dce_version_minor)) {
77                     BREAK_TO_DEBUGGER();
78                     goto failure_1;
79           }
80 
81           /* allocate and initialize business storage */
82           {
83                     const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
84 
85                     index_of_id = 0;
86                     service->ctx = ctx;
87 
88                     do {
89                               uint32_t number_of_bits =
90                                         service->factory.number_of_pins[index_of_id];
91 
92                               uint32_t number_of_uints =
93                                         (number_of_bits + bits_per_uint - 1) /
94                                         bits_per_uint;
95 
96                               uint32_t *slot;
97 
98                               if (number_of_bits) {
99                                         uint32_t index_of_uint = 0;
100 
101                                         slot = kcalloc(number_of_uints,
102                                                          sizeof(uint32_t),
103                                                          GFP_KERNEL);
104 
105                                         if (!slot) {
106                                                   BREAK_TO_DEBUGGER();
107                                                   goto failure_2;
108                                         }
109 
110                                         do {
111                                                   slot[index_of_uint] = 0;
112 
113                                                   ++index_of_uint;
114                                         } while (index_of_uint < number_of_uints);
115                               } else
116                                         slot = NULL;
117 
118                               service->busyness[index_of_id] = slot;
119 
120                               ++index_of_id;
121                     } while (index_of_id < GPIO_ID_COUNT);
122           }
123 
124           return service;
125 
126 failure_2:
127           while (index_of_id) {
128                     uint32_t *slot;
129 
130                     --index_of_id;
131 
132                     slot = service->busyness[index_of_id];
133 
134                     kfree(slot);
135           }
136 
137 failure_1:
138           kfree(service);
139 
140           return NULL;
141 }
142 
dal_gpio_service_create_irq(struct gpio_service * service,uint32_t offset,uint32_t mask)143 struct gpio *dal_gpio_service_create_irq(
144           struct gpio_service *service,
145           uint32_t offset,
146           uint32_t mask)
147 {
148           enum gpio_id id;
149           uint32_t en;
150 
151           if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
152                     ASSERT_CRITICAL(false);
153                     return NULL;
154           }
155 
156           return dal_gpio_create_irq(service, id, en);
157 }
158 
dal_gpio_service_destroy(struct gpio_service ** ptr)159 void dal_gpio_service_destroy(
160           struct gpio_service **ptr)
161 {
162           if (!ptr || !*ptr) {
163                     BREAK_TO_DEBUGGER();
164                     return;
165           }
166 
167           /* free business storage */
168           {
169                     uint32_t index_of_id = 0;
170 
171                     do {
172                               uint32_t *slot = (*ptr)->busyness[index_of_id];
173 
174                               kfree(slot);
175 
176                               ++index_of_id;
177                     } while (index_of_id < GPIO_ID_COUNT);
178           }
179 
180           kfree(*ptr);
181 
182           *ptr = NULL;
183 }
184 
185 /*
186  * @brief
187  * Private API.
188  */
189 
is_pin_busy(const struct gpio_service * service,enum gpio_id id,uint32_t en)190 static bool is_pin_busy(
191           const struct gpio_service *service,
192           enum gpio_id id,
193           uint32_t en)
194 {
195           const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
196 
197           const uint32_t *slot = service->busyness[id] + (en / bits_per_uint);
198 
199           return 0 != (*slot & (1 << (en % bits_per_uint)));
200 }
201 
set_pin_busy(struct gpio_service * service,enum gpio_id id,uint32_t en)202 static void set_pin_busy(
203           struct gpio_service *service,
204           enum gpio_id id,
205           uint32_t en)
206 {
207           const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
208 
209           service->busyness[id][en / bits_per_uint] |=
210                     (1 << (en % bits_per_uint));
211 }
212 
set_pin_free(struct gpio_service * service,enum gpio_id id,uint32_t en)213 static void set_pin_free(
214           struct gpio_service *service,
215           enum gpio_id id,
216           uint32_t en)
217 {
218           const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
219 
220           service->busyness[id][en / bits_per_uint] &=
221                     ~(1 << (en % bits_per_uint));
222 }
223 
dal_gpio_service_open(struct gpio_service * service,enum gpio_id id,uint32_t en,enum gpio_mode mode,struct hw_gpio_pin ** ptr)224 enum gpio_result dal_gpio_service_open(
225           struct gpio_service *service,
226           enum gpio_id id,
227           uint32_t en,
228           enum gpio_mode mode,
229           struct hw_gpio_pin **ptr)
230 {
231           struct hw_gpio_pin *pin;
232 
233           if (!service->busyness[id]) {
234                     ASSERT_CRITICAL(false);
235                     return GPIO_RESULT_OPEN_FAILED;
236           }
237 
238           if (is_pin_busy(service, id, en)) {
239                     ASSERT_CRITICAL(false);
240                     return GPIO_RESULT_DEVICE_BUSY;
241           }
242 
243           switch (id) {
244           case GPIO_ID_DDC_DATA:
245                     pin = service->factory.funcs->create_ddc_data(
246                               service->ctx, id, en);
247                     service->factory.funcs->define_ddc_registers(pin, en);
248           break;
249           case GPIO_ID_DDC_CLOCK:
250                     pin = service->factory.funcs->create_ddc_clock(
251                               service->ctx, id, en);
252                     service->factory.funcs->define_ddc_registers(pin, en);
253           break;
254           case GPIO_ID_GENERIC:
255                     pin = service->factory.funcs->create_generic(
256                               service->ctx, id, en);
257           break;
258           case GPIO_ID_HPD:
259                     pin = service->factory.funcs->create_hpd(
260                               service->ctx, id, en);
261                     service->factory.funcs->define_hpd_registers(pin, en);
262           break;
263           case GPIO_ID_SYNC:
264                     pin = service->factory.funcs->create_sync(
265                               service->ctx, id, en);
266           break;
267           case GPIO_ID_GSL:
268                     pin = service->factory.funcs->create_gsl(
269                               service->ctx, id, en);
270           break;
271           default:
272                     ASSERT_CRITICAL(false);
273                     return GPIO_RESULT_NON_SPECIFIC_ERROR;
274           }
275 
276           if (!pin) {
277                     ASSERT_CRITICAL(false);
278                     return GPIO_RESULT_NON_SPECIFIC_ERROR;
279           }
280 
281           if (!pin->funcs->open(pin, mode)) {
282                     ASSERT_CRITICAL(false);
283                     dal_gpio_service_close(service, &pin);
284                     return GPIO_RESULT_OPEN_FAILED;
285           }
286 
287           set_pin_busy(service, id, en);
288           *ptr = pin;
289           return GPIO_RESULT_OK;
290 }
291 
dal_gpio_service_close(struct gpio_service * service,struct hw_gpio_pin ** ptr)292 void dal_gpio_service_close(
293           struct gpio_service *service,
294           struct hw_gpio_pin **ptr)
295 {
296           struct hw_gpio_pin *pin;
297 
298           if (!ptr) {
299                     ASSERT_CRITICAL(false);
300                     return;
301           }
302 
303           pin = *ptr;
304 
305           if (pin) {
306                     set_pin_free(service, pin->id, pin->en);
307 
308                     pin->funcs->close(pin);
309 
310                     pin->funcs->destroy(ptr);
311           }
312 }
313 
314 
dal_irq_get_source(const struct gpio * irq)315 enum dc_irq_source dal_irq_get_source(
316           const struct gpio *irq)
317 {
318           enum gpio_id id = dal_gpio_get_id(irq);
319 
320           switch (id) {
321           case GPIO_ID_HPD:
322                     return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 +
323                               dal_gpio_get_enum(irq));
324           case GPIO_ID_GPIO_PAD:
325                     return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 +
326                               dal_gpio_get_enum(irq));
327           default:
328                     return DC_IRQ_SOURCE_INVALID;
329           }
330 }
331 
dal_irq_get_rx_source(const struct gpio * irq)332 enum dc_irq_source dal_irq_get_rx_source(
333           const struct gpio *irq)
334 {
335           enum gpio_id id = dal_gpio_get_id(irq);
336 
337           switch (id) {
338           case GPIO_ID_HPD:
339                     return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX +
340                               dal_gpio_get_enum(irq));
341           default:
342                     return DC_IRQ_SOURCE_INVALID;
343           }
344 }
345 
dal_irq_setup_hpd_filter(struct gpio * irq,struct gpio_hpd_config * config)346 enum gpio_result dal_irq_setup_hpd_filter(
347           struct gpio *irq,
348           struct gpio_hpd_config *config)
349 {
350           struct gpio_config_data config_data;
351 
352           if (!config)
353                     return GPIO_RESULT_INVALID_DATA;
354 
355           config_data.type = GPIO_CONFIG_TYPE_HPD;
356           config_data.config.hpd = *config;
357 
358           return dal_gpio_set_config(irq, &config_data);
359 }
360 
361 /*
362  * @brief
363  * Creation and destruction
364  */
365 
dal_gpio_create_irq(struct gpio_service * service,enum gpio_id id,uint32_t en)366 struct gpio *dal_gpio_create_irq(
367           struct gpio_service *service,
368           enum gpio_id id,
369           uint32_t en)
370 {
371           struct gpio *irq;
372 
373           switch (id) {
374           case GPIO_ID_HPD:
375           case GPIO_ID_GPIO_PAD:
376           break;
377           default:
378                     id = GPIO_ID_HPD;
379                     ASSERT_CRITICAL(false);
380                     return NULL;
381           }
382 
383           irq = dal_gpio_create(
384                     service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
385 
386           if (irq)
387                     return irq;
388 
389           ASSERT_CRITICAL(false);
390           return NULL;
391 }
392 
dal_gpio_destroy_irq(struct gpio ** irq)393 void dal_gpio_destroy_irq(
394           struct gpio **irq)
395 {
396           if (!irq || !*irq) {
397                     ASSERT_CRITICAL(false);
398                     return;
399           }
400 
401           dal_gpio_close(*irq);
402           dal_gpio_destroy(irq);
403           kfree(*irq);
404 
405           *irq = NULL;
406 }
407 
dal_gpio_create_ddc(struct gpio_service * service,uint32_t offset,uint32_t mask,struct gpio_ddc_hw_info * info)408 struct ddc *dal_gpio_create_ddc(
409           struct gpio_service *service,
410           uint32_t offset,
411           uint32_t mask,
412           struct gpio_ddc_hw_info *info)
413 {
414           enum gpio_id id;
415           uint32_t en;
416           struct ddc *ddc;
417 
418           if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en))
419                     return NULL;
420 
421           ddc = kzalloc(sizeof(struct ddc), GFP_KERNEL);
422 
423           if (!ddc) {
424                     BREAK_TO_DEBUGGER();
425                     return NULL;
426           }
427 
428           ddc->pin_data = dal_gpio_create(
429                     service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
430 
431           if (!ddc->pin_data) {
432                     BREAK_TO_DEBUGGER();
433                     goto failure_1;
434           }
435 
436           ddc->pin_clock = dal_gpio_create(
437                     service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
438 
439           if (!ddc->pin_clock) {
440                     BREAK_TO_DEBUGGER();
441                     goto failure_2;
442           }
443 
444           ddc->hw_info = *info;
445 
446           ddc->ctx = service->ctx;
447 
448           return ddc;
449 
450 failure_2:
451           dal_gpio_destroy(&ddc->pin_data);
452 
453 failure_1:
454           kfree(ddc);
455 
456           return NULL;
457 }
458 
dal_gpio_destroy_ddc(struct ddc ** ddc)459 void dal_gpio_destroy_ddc(
460           struct ddc **ddc)
461 {
462           if (!ddc || !*ddc) {
463                     BREAK_TO_DEBUGGER();
464                     return;
465           }
466 
467           dal_ddc_close(*ddc);
468           dal_gpio_destroy(&(*ddc)->pin_data);
469           dal_gpio_destroy(&(*ddc)->pin_clock);
470           kfree(*ddc);
471 
472           *ddc = NULL;
473 }
474 
dal_ddc_open(struct ddc * ddc,enum gpio_mode mode,enum gpio_ddc_config_type config_type)475 enum gpio_result dal_ddc_open(
476           struct ddc *ddc,
477           enum gpio_mode mode,
478           enum gpio_ddc_config_type config_type)
479 {
480           enum gpio_result result;
481 
482           struct gpio_config_data config_data;
483           struct hw_gpio *hw_data;
484           struct hw_gpio *hw_clock;
485 
486           result = dal_gpio_open_ex(ddc->pin_data, mode);
487 
488           if (result != GPIO_RESULT_OK) {
489                     BREAK_TO_DEBUGGER();
490                     return result;
491           }
492 
493           result = dal_gpio_open_ex(ddc->pin_clock, mode);
494 
495           if (result != GPIO_RESULT_OK) {
496                     BREAK_TO_DEBUGGER();
497                     goto failure;
498           }
499 
500           /* DDC clock and data pins should belong
501            * to the same DDC block id,
502            * we use the data pin to set the pad mode. */
503 
504           if (mode == GPIO_MODE_INPUT)
505                     /* this is from detect_sink_type,
506                      * we need extra delay there */
507                     config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE;
508           else
509                     config_data.type = GPIO_CONFIG_TYPE_DDC;
510 
511           config_data.config.ddc.type = config_type;
512 
513           hw_data = FROM_HW_GPIO_PIN(ddc->pin_data->pin);
514           hw_clock = FROM_HW_GPIO_PIN(ddc->pin_clock->pin);
515 
516           config_data.config.ddc.data_en_bit_present = hw_data->store.en != 0;
517           config_data.config.ddc.clock_en_bit_present = hw_clock->store.en != 0;
518 
519           result = dal_gpio_set_config(ddc->pin_data, &config_data);
520 
521           if (result == GPIO_RESULT_OK)
522                     return result;
523 
524           BREAK_TO_DEBUGGER();
525 
526           dal_gpio_close(ddc->pin_clock);
527 
528 failure:
529           dal_gpio_close(ddc->pin_data);
530 
531           return result;
532 }
533 
dal_ddc_change_mode(struct ddc * ddc,enum gpio_mode mode)534 enum gpio_result dal_ddc_change_mode(
535           struct ddc *ddc,
536           enum gpio_mode mode)
537 {
538           enum gpio_result result;
539 
540           enum gpio_mode original_mode =
541                     dal_gpio_get_mode(ddc->pin_data);
542 
543           result = dal_gpio_change_mode(ddc->pin_data, mode);
544 
545           /* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR
546            * in case of failures;
547            * set_mode() is so that, in case of failure,
548            * we must explicitly set original mode */
549 
550           if (result != GPIO_RESULT_OK)
551                     goto failure;
552 
553           result = dal_gpio_change_mode(ddc->pin_clock, mode);
554 
555           if (result == GPIO_RESULT_OK)
556                     return result;
557 
558           dal_gpio_change_mode(ddc->pin_clock, original_mode);
559 
560 failure:
561           dal_gpio_change_mode(ddc->pin_data, original_mode);
562 
563           return result;
564 }
565 
dal_ddc_get_line(const struct ddc * ddc)566 enum gpio_ddc_line dal_ddc_get_line(
567           const struct ddc *ddc)
568 {
569           return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data);
570 }
571 
dal_ddc_set_config(struct ddc * ddc,enum gpio_ddc_config_type config_type)572 enum gpio_result dal_ddc_set_config(
573           struct ddc *ddc,
574           enum gpio_ddc_config_type config_type)
575 {
576           struct gpio_config_data config_data;
577 
578           config_data.type = GPIO_CONFIG_TYPE_DDC;
579 
580           config_data.config.ddc.type = config_type;
581           config_data.config.ddc.data_en_bit_present = false;
582           config_data.config.ddc.clock_en_bit_present = false;
583 
584           return dal_gpio_set_config(ddc->pin_data, &config_data);
585 }
586 
dal_ddc_close(struct ddc * ddc)587 void dal_ddc_close(
588           struct ddc *ddc)
589 {
590           dal_gpio_close(ddc->pin_clock);
591           dal_gpio_close(ddc->pin_data);
592 }
593 
594