Lines Matching refs:lpg
87 * struct lpg - LPG device context
107 struct lpg {
137 * @lpg: reference to parent lpg
165 struct lpg *lpg;
203 * @lpg: lpg context reference
210 struct lpg *lpg;
253 static int lpg_clear_pbs_trigger(struct lpg *lpg, unsigned int lut_mask)
258 if (!lpg->lpg_chan_sdam)
261 lpg->pbs_en_bitmap &= (~lut_mask);
262 if (!lpg->pbs_en_bitmap) {
263 rc = nvmem_device_write(lpg->lpg_chan_sdam, SDAM_REG_PBS_SEQ_EN, 1, &val);
267 if (lpg->lut_sdam) {
269 rc = nvmem_device_write(lpg->lpg_chan_sdam, SDAM_PBS_TRIG_CLR, 1, &val);
278 static int lpg_set_pbs_trigger(struct lpg *lpg, unsigned int lut_mask)
283 if (!lpg->lpg_chan_sdam)
286 if (!lpg->pbs_en_bitmap) {
287 rc = nvmem_device_write(lpg->lpg_chan_sdam, SDAM_REG_PBS_SEQ_EN, 1, &val);
291 if (lpg->lut_sdam) {
292 rc = nvmem_device_write(lpg->lpg_chan_sdam, SDAM_PBS_TRIG_SET, 1, &val);
296 rc = qcom_pbs_trigger_event(lpg->pbs_dev, val);
301 lpg->pbs_en_bitmap |= lut_mask;
310 if (!chan->lpg->lpg_chan_sdam)
313 return nvmem_device_write(chan->lpg->lpg_chan_sdam, addr, 1, &set_trig);
316 static int triled_set(struct lpg *lpg, unsigned int mask, unsigned int enable)
319 if (!lpg->triled_base)
322 return regmap_update_bits(lpg->map, lpg->triled_base + TRI_LED_EN_CTL,
326 static int lpg_lut_store_sdam(struct lpg *lpg, struct led_pattern *pattern,
334 if (len > lpg->lut_size) {
335 dev_err(lpg->dev, "Pattern length (%zu) exceeds maximum pattern length (%d)\n",
336 len, lpg->lut_size);
340 idx = bitmap_find_next_zero_area(lpg->lut_bitmap, lpg->lut_size, 0, len, 0);
341 if (idx >= lpg->lut_size)
347 if (lpg->lut_sdam) {
349 rc = nvmem_device_write(lpg->lut_sdam, addr, 1, &brightness);
352 rc = nvmem_device_write(lpg->lpg_chan_sdam, addr, 1, &brightness);
359 bitmap_set(lpg->lut_bitmap, idx, len);
367 static int lpg_lut_store(struct lpg *lpg, struct led_pattern *pattern,
374 idx = bitmap_find_next_zero_area(lpg->lut_bitmap, lpg->lut_size,
376 if (idx >= lpg->lut_size)
382 regmap_bulk_write(lpg->map, lpg->lut_base + LPG_LUT_REG(idx + i),
386 bitmap_set(lpg->lut_bitmap, idx, len);
394 static void lpg_lut_free(struct lpg *lpg, unsigned int lo_idx, unsigned int hi_idx)
402 bitmap_clear(lpg->lut_bitmap, lo_idx, len);
405 static int lpg_lut_sync(struct lpg *lpg, unsigned int mask)
407 if (!lpg->lut_base)
410 return regmap_write(lpg->map, lpg->lut_base + RAMP_CONTROL_REG, mask);
549 struct lpg *lpg = chan->lpg;
573 regmap_write(lpg->map, chan->base + LPG_SIZE_CLK_REG, val);
577 regmap_write(lpg->map, chan->base + LPG_PREDIV_CLK_REG, val);
584 struct lpg *lpg = chan->lpg;
586 regmap_update_bits(lpg->map, chan->base + PWM_TYPE_CONFIG_REG,
592 struct lpg *lpg = chan->lpg;
594 regmap_update_bits(lpg->map, chan->base + PWM_TYPE_CONFIG_REG,
601 struct lpg *lpg = chan->lpg;
607 regmap_bulk_write(lpg->map, chan->base + PWM_VALUE_REG, &val, sizeof(val));
618 struct nvmem_device *lpg_chan_sdam = chan->lpg->lpg_chan_sdam;
623 struct lpg *lpg = chan->lpg;
633 if (chan->ramp_hi_pause_ms && lpg->lut_sdam)
635 if (chan->ramp_lo_pause_ms && lpg->lut_sdam)
638 if (lpg->lut_sdam) {
652 if (lpg->lut_sdam) {
661 struct lpg *lpg = chan->lpg;
686 regmap_write(lpg->map, chan->base + LPG_PATTERN_CONFIG_REG, conf);
687 regmap_write(lpg->map, chan->base + LPG_HI_IDX_REG, hi_idx);
688 regmap_write(lpg->map, chan->base + LPG_LO_IDX_REG, lo_idx);
690 regmap_bulk_write(lpg->map, chan->base + LPG_RAMP_DURATION_REG, &step, sizeof(step));
691 regmap_write(lpg->map, chan->base + LPG_HI_PAUSE_REG, hi_pause);
692 regmap_write(lpg->map, chan->base + LPG_LO_PAUSE_REG, lo_pause);
703 struct lpg *lpg = chan->lpg;
715 regmap_write(lpg->map, chan->base + PWM_ENABLE_CONTROL_REG, ctrl);
729 struct lpg *lpg = chan->lpg;
731 regmap_write(lpg->map, chan->base + PWM_SYNC_REG, LPG_SYNC_PWM);
734 static int lpg_parse_dtest(struct lpg *lpg)
737 struct device_node *np = lpg->dev->of_node;
748 } else if (count != lpg->data->num_channels * 2) {
749 return dev_err_probe(lpg->dev, -EINVAL,
751 lpg->data->num_channels * 2);
754 for (i = 0; i < lpg->data->num_channels; i++) {
755 chan = &lpg->channels[i];
771 return dev_err_probe(lpg->dev, ret, "malformed qcom,dtest\n");
776 struct lpg *lpg = chan->lpg;
781 regmap_write(lpg->map, chan->base + PWM_SEC_ACCESS_REG, 0xa5);
782 regmap_write(lpg->map, chan->base + PWM_DTEST_REG(chan->dtest_line),
793 if (chan->lpg->lpg_chan_sdam)
809 struct lpg *lpg = led->lpg;
846 triled_set(lpg, triled_mask, triled_enabled);
850 lpg_lut_sync(lpg, lut_mask);
851 lpg_set_pbs_trigger(lpg, lut_mask);
861 mutex_lock(&led->lpg->lock);
866 mutex_unlock(&led->lpg->lock);
877 mutex_lock(&led->lpg->lock);
882 mutex_unlock(&led->lpg->lock);
893 struct lpg *lpg = led->lpg;
920 triled_set(lpg, triled_mask, triled_mask);
936 mutex_lock(&led->lpg->lock);
940 mutex_unlock(&led->lpg->lock);
952 mutex_lock(&led->lpg->lock);
956 mutex_unlock(&led->lpg->lock);
965 struct lpg *lpg = led->lpg;
1044 if (lpg->lut_base) {
1088 if (lpg->lut_base || lpg->lut_sdam) {
1097 mutex_lock(&lpg->lock);
1099 if (lpg->lut_base)
1100 ret = lpg_lut_store(lpg, pattern, actual_len, &lo_idx, &hi_idx);
1102 ret = lpg_lut_store_sdam(lpg, pattern, actual_len, &lo_idx, &hi_idx);
1122 mutex_unlock(&lpg->lock);
1156 triled_set(led->lpg, triled_mask, 0);
1171 struct lpg *lpg = led->lpg;
1174 mutex_lock(&lpg->lock);
1177 lpg_lut_free(lpg, chan->pattern_lo_idx, chan->pattern_hi_idx);
1182 lpg_clear_pbs_trigger(chan->lpg, chan->lut_mask);
1187 mutex_unlock(&lpg->lock);
1207 static inline struct lpg *lpg_pwm_from_chip(struct pwm_chip *chip)
1214 struct lpg *lpg = lpg_pwm_from_chip(chip);
1215 struct lpg_channel *chan = &lpg->channels[pwm->hwpwm];
1230 struct lpg *lpg = lpg_pwm_from_chip(chip);
1231 struct lpg_channel *chan = &lpg->channels[pwm->hwpwm];
1237 mutex_lock(&lpg->lock);
1250 triled_set(lpg, chan->triled_mask, chan->enabled ? chan->triled_mask : 0);
1253 mutex_unlock(&lpg->lock);
1261 struct lpg *lpg = lpg_pwm_from_chip(chip);
1262 struct lpg_channel *chan = &lpg->channels[pwm->hwpwm];
1271 ret = regmap_read(lpg->map, chan->base + LPG_SIZE_CLK_REG, &val);
1284 ret = regmap_read(lpg->map, chan->base + LPG_PREDIV_CLK_REG, &val);
1291 ret = regmap_bulk_read(lpg->map, chan->base + PWM_VALUE_REG, &pwm_value, sizeof(pwm_value));
1303 ret = regmap_read(lpg->map, chan->base + PWM_ENABLE_CONTROL_REG, &val);
1322 static int lpg_add_pwm(struct lpg *lpg)
1327 lpg->pwm = chip = devm_pwmchip_alloc(lpg->dev, lpg->num_channels, 0);
1332 pwmchip_set_drvdata(chip, lpg);
1334 ret = devm_pwmchip_add(lpg->dev, chip);
1336 dev_err_probe(lpg->dev, ret, "failed to add PWM chip\n");
1341 static int lpg_parse_channel(struct lpg *lpg, struct device_node *np,
1350 if (ret || !reg || reg > lpg->num_channels)
1351 return dev_err_probe(lpg->dev, -EINVAL, "invalid \"reg\" of %pOFn\n", np);
1353 chan = &lpg->channels[reg - 1];
1358 return dev_err_probe(lpg->dev, ret,
1368 static int lpg_add_led(struct lpg *lpg, struct device_node *np)
1382 return dev_err_probe(lpg->dev, ret,
1390 led = devm_kzalloc(lpg->dev, struct_size(led, channels, num_channels), GFP_KERNEL);
1394 led->lpg = lpg;
1398 info = devm_kcalloc(lpg->dev, num_channels, sizeof(*info), GFP_KERNEL);
1403 ret = lpg_parse_channel(lpg, child, &led->channels[i]);
1420 if (lpg->lut_base || lpg->lpg_chan_sdam) {
1425 ret = lpg_parse_channel(lpg, np, &led->channels[0]);
1434 if (lpg->lut_base || lpg->lpg_chan_sdam) {
1442 if (lpg->lpg_chan_sdam)
1458 ret = devm_led_classdev_multicolor_register_ext(lpg->dev, &led->mcdev, &init_data);
1460 ret = devm_led_classdev_register_ext(lpg->dev, &led->cdev, &init_data);
1462 dev_err_probe(lpg->dev, ret, "unable to register %s\n", cdev->name);
1467 static int lpg_init_channels(struct lpg *lpg)
1469 const struct lpg_data *data = lpg->data;
1473 lpg->num_channels = data->num_channels;
1474 lpg->channels = devm_kcalloc(lpg->dev, data->num_channels,
1476 if (!lpg->channels)
1480 chan = &lpg->channels[i];
1482 chan->lpg = lpg;
1488 regmap_read(lpg->map, chan->base + LPG_SUBTYPE_REG, &chan->subtype);
1494 static int lpg_init_triled(struct lpg *lpg)
1496 struct device_node *np = lpg->dev->of_node;
1500 if (!lpg->data->triled_base)
1503 lpg->triled_base = lpg->data->triled_base;
1504 lpg->triled_has_atc_ctl = lpg->data->triled_has_atc_ctl;
1505 lpg->triled_has_src_sel = lpg->data->triled_has_src_sel;
1507 if (lpg->triled_has_src_sel) {
1508 ret = of_property_read_u32(np, "qcom,power-source", &lpg->triled_src);
1509 if (ret || lpg->triled_src == 2 || lpg->triled_src > 3)
1510 return dev_err_probe(lpg->dev, -EINVAL,
1515 if (lpg->triled_has_atc_ctl)
1516 regmap_write(lpg->map, lpg->triled_base + TRI_LED_ATC_CTL, 0);
1519 if (lpg->triled_has_src_sel)
1520 regmap_write(lpg->map, lpg->triled_base + TRI_LED_SRC_SEL, lpg->triled_src);
1523 regmap_write(lpg->map, lpg->triled_base + TRI_LED_EN_CTL, 0);
1528 static int lpg_init_lut(struct lpg *lpg)
1530 const struct lpg_data *data = lpg->data;
1535 lpg->lut_size = data->lut_size;
1537 lpg->lut_base = data->lut_base;
1539 lpg->lut_bitmap = devm_bitmap_zalloc(lpg->dev, lpg->lut_size, GFP_KERNEL);
1540 if (!lpg->lut_bitmap)
1546 static int lpg_init_sdam(struct lpg *lpg)
1551 sdam_count = of_property_count_strings(lpg->dev->of_node, "nvmem-names");
1558 lpg->lpg_chan_sdam = devm_nvmem_device_get(lpg->dev, "lpg_chan_sdam");
1559 if (IS_ERR(lpg->lpg_chan_sdam))
1560 return dev_err_probe(lpg->dev, PTR_ERR(lpg->lpg_chan_sdam),
1565 lpg->pbs_dev = get_pbs_client_device(lpg->dev);
1566 if (IS_ERR(lpg->pbs_dev))
1567 return dev_err_probe(lpg->dev, PTR_ERR(lpg->pbs_dev),
1571 lpg->lut_sdam = devm_nvmem_device_get(lpg->dev, "lut_sdam");
1572 if (IS_ERR(lpg->lut_sdam))
1573 return dev_err_probe(lpg->dev, PTR_ERR(lpg->lut_sdam),
1577 for (i = 0; i < lpg->num_channels; i++) {
1578 struct lpg_channel *chan = &lpg->channels[i];
1581 rc = nvmem_device_write(lpg->lpg_chan_sdam,
1590 rc = lpg_clear_pbs_trigger(chan->lpg, chan->lut_mask);
1601 struct lpg *lpg;
1605 lpg = devm_kzalloc(&pdev->dev, sizeof(*lpg), GFP_KERNEL);
1606 if (!lpg)
1609 lpg->data = of_device_get_match_data(&pdev->dev);
1610 if (!lpg->data)
1613 lpg->dev = &pdev->dev;
1614 mutex_init(&lpg->lock);
1616 lpg->map = dev_get_regmap(pdev->dev.parent, NULL);
1617 if (!lpg->map)
1620 ret = lpg_init_channels(lpg);
1624 ret = lpg_parse_dtest(lpg);
1628 ret = lpg_init_triled(lpg);
1632 ret = lpg_init_sdam(lpg);
1636 ret = lpg_init_lut(lpg);
1641 ret = lpg_add_led(lpg, np);
1646 for (i = 0; i < lpg->num_channels; i++)
1647 lpg_apply_dtest(&lpg->channels[i]);
1649 return lpg_add_pwm(lpg);
1822 { .compatible = "qcom,pm660l-lpg", .data = &pm660l_lpg_data },
1823 { .compatible = "qcom,pm8150b-lpg", .data = &pm8150b_lpg_data },
1824 { .compatible = "qcom,pm8150l-lpg", .data = &pm8150l_lpg_data },
1827 { .compatible = "qcom,pm8941-lpg", .data = &pm8941_lpg_data },
1828 { .compatible = "qcom,pm8994-lpg", .data = &pm8994_lpg_data },
1829 { .compatible = "qcom,pmi632-lpg", .data = &pmi632_lpg_data },
1831 { .compatible = "qcom,pmi8994-lpg", .data = &pmi8994_lpg_data },
1832 { .compatible = "qcom,pmi8998-lpg", .data = &pmi8998_lpg_data },
1833 { .compatible = "qcom,pmc8180c-lpg", .data = &pm8150l_lpg_data },
1842 .name = "qcom-spmi-lpg",