diff mbox

[08/14] OMAPDSS: DSS: add new clock calculation code

Message ID 1362743569-10289-9-git-send-email-tomi.valkeinen@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tomi Valkeinen March 8, 2013, 11:52 a.m. UTC
Add new way to iterate over DSS clock divisors. dss_div_calc() provides
a generic way to go over all the divisors, within given clock range.
dss_div_calc() will call a callback function for each divider set,
making the function reusable for all use cases.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.c |   36 ++++++++++++++++++++++++++++++++++++
 drivers/video/omap2/dss/dss.h |    3 +++
 2 files changed, 39 insertions(+)

Comments

archit taneja March 20, 2013, 3:17 p.m. UTC | #1
On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
> Add new way to iterate over DSS clock divisors. dss_div_calc() provides
> a generic way to go over all the divisors, within given clock range.
> dss_div_calc() will call a callback function for each divider set,
> making the function reusable for all use cases.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> ---
>   drivers/video/omap2/dss/dss.c |   36 ++++++++++++++++++++++++++++++++++++
>   drivers/video/omap2/dss/dss.h |    3 +++
>   2 files changed, 39 insertions(+)
>
> diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
> index 054c2a2..21a3dc8 100644
> --- a/drivers/video/omap2/dss/dss.c
> +++ b/drivers/video/omap2/dss/dss.c
> @@ -473,6 +473,42 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
>   	return 0;
>   }
>
> +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
> +{
> +	int fckd, fckd_start, fckd_stop;
> +	unsigned long fck;
> +	unsigned long fck_hw_max;
> +	unsigned long fckd_hw_max;
> +	unsigned long prate;
> +
> +	if (dss.dpll4_m4_ck == NULL) {
> +		/* XXX can we change the clock on omap2? */

We can change dss_fclk1 on omap2, and the cclock2420_data.c and 
cclock2430_data.c have clksel structs which allow a set of dividers. The 
dividers are not continuous though, 1 to 12 and 16 are allowed. So we 
might need to change the code here a bit, if we want to change the clock 
in the first place.

Archit

> +		fck = clk_get_rate(dss.dss_clk);
> +		fckd = 1;
> +
> +		return func(fckd, fck, data);
> +	}
> +
> +	fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
> +	fckd_hw_max = dss.feat->fck_div_max;
> +
> +	prate = dss_get_dpll4_rate() * dss.feat->dss_fck_multiplier;
> +
> +	fck_min = fck_min ? fck_min : 1;
> +
> +	fckd_start = min(prate / fck_min, fckd_hw_max);
> +	fckd_stop = max(DIV_ROUND_UP(prate, fck_hw_max), 1ul);
> +
> +	for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
> +		fck = prate / fckd;
> +
> +		if (func(fckd, fck, data))
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
>   int dss_set_clock_div(struct dss_clock_info *cinfo)
>   {
>   	if (dss.dpll4_m4_ck) {
> diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
> index 0ff41dd..4180302 100644
> --- a/drivers/video/omap2/dss/dss.h
> +++ b/drivers/video/omap2/dss/dss.h
> @@ -271,6 +271,9 @@ int dss_set_clock_div(struct dss_clock_info *cinfo);
>   int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
>   		struct dispc_clock_info *dispc_cinfo);
>
> +typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data);
> +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data);
> +
>   /* SDI */
>   int sdi_init_platform_driver(void) __init;
>   void sdi_uninit_platform_driver(void) __exit;
>

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tomi Valkeinen March 20, 2013, 3:28 p.m. UTC | #2
On 2013-03-20 17:17, Archit Taneja wrote:
> On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
>> Add new way to iterate over DSS clock divisors. dss_div_calc() provides
>> a generic way to go over all the divisors, within given clock range.
>> dss_div_calc() will call a callback function for each divider set,
>> making the function reusable for all use cases.
>>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
>> ---
>>   drivers/video/omap2/dss/dss.c |   36
>> ++++++++++++++++++++++++++++++++++++
>>   drivers/video/omap2/dss/dss.h |    3 +++
>>   2 files changed, 39 insertions(+)
>>
>> diff --git a/drivers/video/omap2/dss/dss.c
>> b/drivers/video/omap2/dss/dss.c
>> index 054c2a2..21a3dc8 100644
>> --- a/drivers/video/omap2/dss/dss.c
>> +++ b/drivers/video/omap2/dss/dss.c
>> @@ -473,6 +473,42 @@ int dss_calc_clock_rates(struct dss_clock_info
>> *cinfo)
>>       return 0;
>>   }
>>
>> +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void
>> *data)
>> +{
>> +    int fckd, fckd_start, fckd_stop;
>> +    unsigned long fck;
>> +    unsigned long fck_hw_max;
>> +    unsigned long fckd_hw_max;
>> +    unsigned long prate;
>> +
>> +    if (dss.dpll4_m4_ck == NULL) {
>> +        /* XXX can we change the clock on omap2? */
> 
> We can change dss_fclk1 on omap2, and the cclock2420_data.c and
> cclock2430_data.c have clksel structs which allow a set of dividers. The
> dividers are not continuous though, 1 to 12 and 16 are allowed. So we
> might need to change the code here a bit, if we want to change the clock
> in the first place.

Ok, good to know. Note that the comment is copied from the old code. I
think I tried changing the clock on N800 with clk_set_rate long ago, but
I didn't get it to work. Things might have changed, but, well, I don't
think we should spend time on omap2 code. I'm sure we'll get a patch if
somebody needs it =).

 Tomi
archit taneja March 21, 2013, 6:14 a.m. UTC | #3
On Wednesday 20 March 2013 08:58 PM, Tomi Valkeinen wrote:
> On 2013-03-20 17:17, Archit Taneja wrote:
>> On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
>>> Add new way to iterate over DSS clock divisors. dss_div_calc() provides
>>> a generic way to go over all the divisors, within given clock range.
>>> dss_div_calc() will call a callback function for each divider set,
>>> making the function reusable for all use cases.
>>>
>>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
>>> ---
>>>    drivers/video/omap2/dss/dss.c |   36
>>> ++++++++++++++++++++++++++++++++++++
>>>    drivers/video/omap2/dss/dss.h |    3 +++
>>>    2 files changed, 39 insertions(+)
>>>
>>> diff --git a/drivers/video/omap2/dss/dss.c
>>> b/drivers/video/omap2/dss/dss.c
>>> index 054c2a2..21a3dc8 100644
>>> --- a/drivers/video/omap2/dss/dss.c
>>> +++ b/drivers/video/omap2/dss/dss.c
>>> @@ -473,6 +473,42 @@ int dss_calc_clock_rates(struct dss_clock_info
>>> *cinfo)
>>>        return 0;
>>>    }
>>>
>>> +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void
>>> *data)
>>> +{
>>> +    int fckd, fckd_start, fckd_stop;
>>> +    unsigned long fck;
>>> +    unsigned long fck_hw_max;
>>> +    unsigned long fckd_hw_max;
>>> +    unsigned long prate;
>>> +
>>> +    if (dss.dpll4_m4_ck == NULL) {
>>> +        /* XXX can we change the clock on omap2? */
>>
>> We can change dss_fclk1 on omap2, and the cclock2420_data.c and
>> cclock2430_data.c have clksel structs which allow a set of dividers. The
>> dividers are not continuous though, 1 to 12 and 16 are allowed. So we
>> might need to change the code here a bit, if we want to change the clock
>> in the first place.
>
> Ok, good to know. Note that the comment is copied from the old code. I
> think I tried changing the clock on N800 with clk_set_rate long ago, but
> I didn't get it to work. Things might have changed, but, well, I don't
> think we should spend time on omap2 code. I'm sure we'll get a patch if
> somebody needs it =).

We could change the comment to a TODO for now.

Archit

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tomi Valkeinen March 21, 2013, 8:13 a.m. UTC | #4
On 2013-03-21 08:14, Archit Taneja wrote:
> On Wednesday 20 March 2013 08:58 PM, Tomi Valkeinen wrote:
>> On 2013-03-20 17:17, Archit Taneja wrote:
>>> On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:

>>>> +    if (dss.dpll4_m4_ck == NULL) {
>>>> +        /* XXX can we change the clock on omap2? */
>>>
>>> We can change dss_fclk1 on omap2, and the cclock2420_data.c and
>>> cclock2430_data.c have clksel structs which allow a set of dividers. The
>>> dividers are not continuous though, 1 to 12 and 16 are allowed. So we
>>> might need to change the code here a bit, if we want to change the clock
>>> in the first place.
>>
>> Ok, good to know. Note that the comment is copied from the old code. I
>> think I tried changing the clock on N800 with clk_set_rate long ago, but
>> I didn't get it to work. Things might have changed, but, well, I don't
>> think we should spend time on omap2 code. I'm sure we'll get a patch if
>> somebody needs it =).
> 
> We could change the comment to a TODO for now.

Yep, not a bad idea. I'll make the change.

 Tomi
diff mbox

Patch

diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 054c2a2..21a3dc8 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -473,6 +473,42 @@  int dss_calc_clock_rates(struct dss_clock_info *cinfo)
 	return 0;
 }
 
+bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
+{
+	int fckd, fckd_start, fckd_stop;
+	unsigned long fck;
+	unsigned long fck_hw_max;
+	unsigned long fckd_hw_max;
+	unsigned long prate;
+
+	if (dss.dpll4_m4_ck == NULL) {
+		/* XXX can we change the clock on omap2? */
+		fck = clk_get_rate(dss.dss_clk);
+		fckd = 1;
+
+		return func(fckd, fck, data);
+	}
+
+	fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+	fckd_hw_max = dss.feat->fck_div_max;
+
+	prate = dss_get_dpll4_rate() * dss.feat->dss_fck_multiplier;
+
+	fck_min = fck_min ? fck_min : 1;
+
+	fckd_start = min(prate / fck_min, fckd_hw_max);
+	fckd_stop = max(DIV_ROUND_UP(prate, fck_hw_max), 1ul);
+
+	for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
+		fck = prate / fckd;
+
+		if (func(fckd, fck, data))
+			return true;
+	}
+
+	return false;
+}
+
 int dss_set_clock_div(struct dss_clock_info *cinfo)
 {
 	if (dss.dpll4_m4_ck) {
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 0ff41dd..4180302 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -271,6 +271,9 @@  int dss_set_clock_div(struct dss_clock_info *cinfo);
 int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
 		struct dispc_clock_info *dispc_cinfo);
 
+typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data);
+bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data);
+
 /* SDI */
 int sdi_init_platform_driver(void) __init;
 void sdi_uninit_platform_driver(void) __exit;